diff --git a/docs/QuEST_8c.html b/docs/QuEST_8c.html index de667cdfe..cfdfd351b 100644 --- a/docs/QuEST_8c.html +++ b/docs/QuEST_8c.html @@ -27,7 +27,7 @@
@@ -120,6 +120,9 @@ void applyPhaseFuncOverrides (Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)  Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices. More...
  +void applyProjector (Qureg qureg, int qubit, int outcome) + Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection. More...
+  void applyQFT (Qureg qureg, int *qubits, int numQubits)  Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg. More...
  @@ -269,6 +272,9 @@   int getQuEST_PREC (void)   +void getQuESTSeeds (QuESTEnv env, unsigned long int **seeds, int *numSeeds) + Obtain the seeds presently used in random number generation. More...
qreal getRealAmp (Qureg qureg, long long int index)  Get the real component of the complex probability amplitude at an index in the state vector. More...
  @@ -303,7 +309,7 @@  Initialise qureg into to a given pure state of an equivalent Hilbert dimension. More...
  void initStateFromAmps (Qureg qureg, qreal *reals, qreal *imags) - Initialise state-vector qureg by specifying all amplitudes. More...
+ Initialise qureg by specifying all amplitudes. More...
  void initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)  Initialises the wavefunction amplitudes according to those specified in a file. More...
@@ -422,6 +428,9 @@ void rotateZ (Qureg qureg, int targetQubit, qreal angle)  Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate). More...
  +void seedQuESTDefault (QuESTEnv *env) + Seeds the random number generator with the (master node) current time and process ID. More...
+  void setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)  Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags. More...
  @@ -513,13 +522,13 @@

Definition at line 1558 of file QuEST.c.

-
1558  {
-
1559  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1560  return statevec_compareStates(qureg1, qureg2, precision);
-
1561 }
+

Definition at line 1573 of file QuEST.c.

+
1573  {
+
1574  validateMatchingQuregDims(qureg1, qureg2, __func__);
+
1575  return statevec_compareStates(qureg1, qureg2, precision);
+
1576 }
-

References statevec_compareStates(), and validateMatchingQuregDims().

+

References statevec_compareStates(), and validateMatchingQuregDims().

@@ -539,10 +548,10 @@

-

Definition at line 1595 of file QuEST.c.

-
1595  {
-
1596  return sizeof(qreal)/4;
-
1597 }
+

Definition at line 1610 of file QuEST.c.

+
1610  {
+
1611  return sizeof(qreal)/4;
+
1612 }

References qreal.

@@ -583,13 +592,13 @@

Definition at line 1567 of file QuEST.c.

-
1567  {
-
1568  int success = statevec_initStateFromSingleFile(qureg, filename, env);
-
1569  validateFileOpened(success, filename, __func__);
-
1570 }
+

Definition at line 1582 of file QuEST.c.

+
1582  {
+
1583  int success = statevec_initStateFromSingleFile(qureg, filename, env);
+
1584  validateFileOpened(success, filename, __func__);
+
1585 }
-

References statevec_initStateFromSingleFile(), and validateFileOpened().

+

References statevec_initStateFromSingleFile(), and validateFileOpened().

@@ -635,15 +644,15 @@

Definition at line 1572 of file QuEST.c.

-
1572  {
-
1573  validateStateVecQureg(*qureg, __func__);
-
1574  validateTarget(*qureg, qubitId, __func__);
-
1575  validateOutcome(outcome, __func__);
-
1576  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
-
1577 }
+

Definition at line 1587 of file QuEST.c.

+
1587  {
+
1588  validateStateVecQureg(*qureg, __func__);
+
1589  validateTarget(*qureg, qubitId, __func__);
+
1590  validateOutcome(outcome, __func__);
+
1591  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
+
1592 }
-

References statevec_initStateOfSingleQubit(), validateOutcome(), validateStateVecQureg(), and validateTarget().

+

References statevec_initStateOfSingleQubit(), validateOutcome(), validateStateVecQureg(), and validateTarget().

@@ -682,31 +691,31 @@

Definition at line 1017 of file QuEST.c.

-
1017  {
-
1018  long long int numAmps = qureg.numAmpsTotal;
-
1019  statevec_setAmps(qureg, 0, reals, imags, numAmps);
-
1020 
-
1021  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
-
1022 }
+

Definition at line 1030 of file QuEST.c.

+
1030  {
+
1031  long long int numAmps = qureg.numAmpsTotal;
+
1032  statevec_setAmps(qureg, 0, reals, imags, numAmps);
+
1033 
+
1034  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
+
1035 }
-

References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

+

References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1600
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void validateOutcome(int outcome, const char *caller)
+
void validateStateVecQureg(Qureg qureg, const char *caller)
+
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1611
#define qreal
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
+
void validateFileOpened(int opened, char *fn, const char *caller)
+
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1248
+
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1680
+
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1691
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1730
+
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1741
diff --git a/docs/QuEST_8c_source.html b/docs/QuEST_8c_source.html index 4e50aee23..9f694636d 100644 --- a/docs/QuEST_8c_source.html +++ b/docs/QuEST_8c_source.html @@ -27,7 +27,7 @@ @@ -200,1840 +200,1875 @@
155 }
156 
157 void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags) {
-
158  validateStateVecQureg(qureg, __func__);
-
159 
-
160  statevec_setAmps(qureg, 0, reals, imags, qureg.numAmpsTotal);
-
161 
-
162  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
-
163 }
-
164 
-
165 void cloneQureg(Qureg targetQureg, Qureg copyQureg) {
-
166  validateMatchingQuregTypes(targetQureg, copyQureg, __func__);
-
167  validateMatchingQuregDims(targetQureg, copyQureg, __func__);
-
168 
-
169  statevec_cloneQureg(targetQureg, copyQureg);
-
170 }
+
158 
+
159  statevec_setAmps(qureg, 0, reals, imags, qureg.numAmpsTotal);
+
160 
+
161  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
+
162 }
+
163 
+
164 void cloneQureg(Qureg targetQureg, Qureg copyQureg) {
+
165  validateMatchingQuregTypes(targetQureg, copyQureg, __func__);
+
166  validateMatchingQuregDims(targetQureg, copyQureg, __func__);
+
167 
+
168  statevec_cloneQureg(targetQureg, copyQureg);
+
169 }
+
170 
171 
-
172 
-
173 /*
-
174  * unitary gates
-
175  */
-
176 
-
177 void hadamard(Qureg qureg, int targetQubit) {
-
178  validateTarget(qureg, targetQubit, __func__);
-
179 
-
180  statevec_hadamard(qureg, targetQubit);
-
181  if (qureg.isDensityMatrix) {
-
182  statevec_hadamard(qureg, targetQubit+qureg.numQubitsRepresented);
-
183  }
-
184 
-
185  qasm_recordGate(qureg, GATE_HADAMARD, targetQubit);
-
186 }
-
187 
-
188 void rotateX(Qureg qureg, int targetQubit, qreal angle) {
-
189  validateTarget(qureg, targetQubit, __func__);
-
190 
-
191  statevec_rotateX(qureg, targetQubit, angle);
-
192  if (qureg.isDensityMatrix) {
-
193  statevec_rotateX(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
-
194  }
-
195 
-
196  qasm_recordParamGate(qureg, GATE_ROTATE_X, targetQubit, angle);
-
197 }
-
198 
-
199 void rotateY(Qureg qureg, int targetQubit, qreal angle) {
-
200  validateTarget(qureg, targetQubit, __func__);
-
201 
-
202  statevec_rotateY(qureg, targetQubit, angle);
-
203  if (qureg.isDensityMatrix) {
-
204  statevec_rotateY(qureg, targetQubit+qureg.numQubitsRepresented, angle);
-
205  }
-
206 
-
207  qasm_recordParamGate(qureg, GATE_ROTATE_Y, targetQubit, angle);
-
208 }
-
209 
-
210 void rotateZ(Qureg qureg, int targetQubit, qreal angle) {
-
211  validateTarget(qureg, targetQubit, __func__);
-
212 
-
213  statevec_rotateZ(qureg, targetQubit, angle);
-
214  if (qureg.isDensityMatrix) {
-
215  statevec_rotateZ(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
-
216  }
-
217 
-
218  qasm_recordParamGate(qureg, GATE_ROTATE_Z, targetQubit, angle);
-
219 }
-
220 
-
221 void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
-
222  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
223 
-
224  statevec_controlledRotateX(qureg, controlQubit, targetQubit, angle);
-
225  if (qureg.isDensityMatrix) {
-
226  int shift = qureg.numQubitsRepresented;
-
227  statevec_controlledRotateX(qureg, controlQubit+shift, targetQubit+shift, -angle);
-
228  }
-
229 
-
230  qasm_recordControlledParamGate(qureg, GATE_ROTATE_X, controlQubit, targetQubit, angle);
-
231 }
-
232 
-
233 void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
-
234  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
235 
-
236  statevec_controlledRotateY(qureg, controlQubit, targetQubit, angle);
-
237  if (qureg.isDensityMatrix) {
-
238  int shift = qureg.numQubitsRepresented;
-
239  statevec_controlledRotateY(qureg, controlQubit+shift, targetQubit+shift, angle); // rotateY is real
-
240  }
-
241 
-
242  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Y, controlQubit, targetQubit, angle);
-
243 }
-
244 
-
245 void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
-
246  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
247 
-
248  statevec_controlledRotateZ(qureg, controlQubit, targetQubit, angle);
-
249  if (qureg.isDensityMatrix) {
-
250  int shift = qureg.numQubitsRepresented;
-
251  statevec_controlledRotateZ(qureg, controlQubit+shift, targetQubit+shift, -angle);
-
252  }
-
253 
-
254  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Z, controlQubit, targetQubit, angle);
-
255 }
-
256 
-
257 void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
258  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
-
259  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
-
260 
-
261  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
-
262  if (qureg.isDensityMatrix) {
-
263  int shift = qureg.numQubitsRepresented;
-
264  statevec_twoQubitUnitary(qureg, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
-
265  }
-
266 
-
267  qasm_recordComment(qureg, "Here, an undisclosed 2-qubit unitary was applied.");
-
268 }
-
269 
-
270 void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
271  validateMultiControlsMultiTargets(qureg, (int[]) {controlQubit}, 1, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
-
272  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
-
273 
-
274  statevec_controlledTwoQubitUnitary(qureg, controlQubit, targetQubit1, targetQubit2, u);
-
275  if (qureg.isDensityMatrix) {
-
276  int shift = qureg.numQubitsRepresented;
-
277  statevec_controlledTwoQubitUnitary(qureg, controlQubit+shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
-
278  }
-
279 
-
280  qasm_recordComment(qureg, "Here, an undisclosed controlled 2-qubit unitary was applied.");
-
281 }
-
282 
-
283 void multiControlledTwoQubitUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
284  validateMultiControlsMultiTargets(qureg, controlQubits, numControlQubits, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
-
285  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
-
286 
-
287  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
-
288  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask, targetQubit1, targetQubit2, u);
-
289  if (qureg.isDensityMatrix) {
-
290  int shift = qureg.numQubitsRepresented;
-
291  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask<<shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
-
292  }
-
293 
-
294  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled 2-qubit unitary was applied.");
-
295 }
-
296 
-
297 void multiQubitUnitary(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u) {
-
298  validateMultiTargets(qureg, targs, numTargs, __func__);
-
299  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
-
300 
-
301  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
-
302  if (qureg.isDensityMatrix) {
-
303  int shift = qureg.numQubitsRepresented;
-
304  shiftIndices(targs, numTargs, shift);
- -
306  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
-
307  shiftIndices(targs, numTargs, -shift);
- -
309  }
-
310 
-
311  qasm_recordComment(qureg, "Here, an undisclosed multi-qubit unitary was applied.");
-
312 }
-
313 
-
314 void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targs, int numTargs, ComplexMatrixN u) {
-
315  validateMultiControlsMultiTargets(qureg, (int[]) {ctrl}, 1, targs, numTargs, __func__);
-
316  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
-
317 
-
318  statevec_controlledMultiQubitUnitary(qureg, ctrl, targs, numTargs, u);
-
319  if (qureg.isDensityMatrix) {
-
320  int shift = qureg.numQubitsRepresented;
-
321  shiftIndices(targs, numTargs, shift);
- -
323  statevec_controlledMultiQubitUnitary(qureg, ctrl+shift, targs, numTargs, u);
-
324  shiftIndices(targs, numTargs, -shift);
- -
326  }
-
327 
-
328  qasm_recordComment(qureg, "Here, an undisclosed controlled multi-qubit unitary was applied.");
-
329 }
-
330 
-
331 void multiControlledMultiQubitUnitary(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u) {
-
332  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
-
333  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
-
334 
-
335  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
-
336  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
-
337  if (qureg.isDensityMatrix) {
-
338  int shift = qureg.numQubitsRepresented;
-
339  shiftIndices(targs, numTargs, shift);
- -
341  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask<<shift, targs, numTargs, u);
-
342  shiftIndices(targs, numTargs, -shift);
- -
344  }
-
345 
-
346  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled multi-qubit unitary was applied.");
-
347 }
-
348 
-
349 void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u) {
-
350  validateTarget(qureg, targetQubit, __func__);
-
351  validateOneQubitUnitaryMatrix(u, __func__);
-
352 
-
353  statevec_unitary(qureg, targetQubit, u);
-
354  if (qureg.isDensityMatrix) {
-
355  statevec_unitary(qureg, targetQubit+qureg.numQubitsRepresented, getConjugateMatrix2(u));
-
356  }
-
357 
-
358  qasm_recordUnitary(qureg, u, targetQubit);
-
359 }
-
360 
-
361 void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u) {
-
362  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
363  validateOneQubitUnitaryMatrix(u, __func__);
-
364 
-
365  statevec_controlledUnitary(qureg, controlQubit, targetQubit, u);
-
366  if (qureg.isDensityMatrix) {
-
367  int shift = qureg.numQubitsRepresented;
-
368  statevec_controlledUnitary(qureg, controlQubit+shift, targetQubit+shift, getConjugateMatrix2(u));
-
369  }
-
370 
-
371  qasm_recordControlledUnitary(qureg, u, controlQubit, targetQubit);
-
372 }
-
373 
-
374 void multiControlledUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u) {
-
375  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
-
376  validateOneQubitUnitaryMatrix(u, __func__);
-
377 
-
378  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
-
379  long long int ctrlFlipMask = 0;
-
380  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
-
381  if (qureg.isDensityMatrix) {
-
382  int shift = qureg.numQubitsRepresented;
-
383  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
-
384  }
-
385 
-
386  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
-
387 }
-
388 
-
389 void multiStateControlledUnitary(Qureg qureg, int* controlQubits, int* controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u) {
-
390  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
-
391  validateOneQubitUnitaryMatrix(u, __func__);
-
392  validateControlState(controlState, numControlQubits, __func__);
-
393 
-
394  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
-
395  long long int ctrlFlipMask = getControlFlipMask(controlQubits, controlState, numControlQubits);
-
396  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
-
397  if (qureg.isDensityMatrix) {
-
398  int shift = qureg.numQubitsRepresented;
-
399  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
-
400  }
-
401 
-
402  qasm_recordMultiStateControlledUnitary(qureg, u, controlQubits, controlState, numControlQubits, targetQubit);
-
403 }
-
404 
-
405 void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta) {
-
406  validateTarget(qureg, targetQubit, __func__);
-
407  validateUnitaryComplexPair(alpha, beta, __func__);
-
408 
-
409  statevec_compactUnitary(qureg, targetQubit, alpha, beta);
-
410  if (qureg.isDensityMatrix) {
-
411  int shift = qureg.numQubitsRepresented;
-
412  statevec_compactUnitary(qureg, targetQubit+shift, getConjugateScalar(alpha), getConjugateScalar(beta));
-
413  }
-
414 
-
415  qasm_recordCompactUnitary(qureg, alpha, beta, targetQubit);
-
416 }
-
417 
-
418 void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta) {
-
419  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
420  validateUnitaryComplexPair(alpha, beta, __func__);
-
421 
-
422  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
423  if (qureg.isDensityMatrix) {
-
424  int shift = qureg.numQubitsRepresented;
- -
426  controlQubit+shift, targetQubit+shift,
-
427  getConjugateScalar(alpha), getConjugateScalar(beta));
-
428  }
-
429 
-
430  qasm_recordControlledCompactUnitary(qureg, alpha, beta, controlQubit, targetQubit);
-
431 }
-
432 
-
433 void pauliX(Qureg qureg, int targetQubit) {
-
434  validateTarget(qureg, targetQubit, __func__);
-
435 
-
436  statevec_pauliX(qureg, targetQubit);
-
437  if (qureg.isDensityMatrix) {
-
438  statevec_pauliX(qureg, targetQubit+qureg.numQubitsRepresented);
-
439  }
-
440 
-
441  qasm_recordGate(qureg, GATE_SIGMA_X, targetQubit);
-
442 }
-
443 
-
444 void pauliY(Qureg qureg, int targetQubit) {
-
445  validateTarget(qureg, targetQubit, __func__);
-
446 
-
447  statevec_pauliY(qureg, targetQubit);
-
448  if (qureg.isDensityMatrix) {
-
449  statevec_pauliYConj(qureg, targetQubit + qureg.numQubitsRepresented);
-
450  }
-
451 
-
452  qasm_recordGate(qureg, GATE_SIGMA_Y, targetQubit);
-
453 }
-
454 
-
455 void pauliZ(Qureg qureg, int targetQubit) {
-
456  validateTarget(qureg, targetQubit, __func__);
-
457 
-
458  statevec_pauliZ(qureg, targetQubit);
-
459  if (qureg.isDensityMatrix) {
-
460  statevec_pauliZ(qureg, targetQubit+qureg.numQubitsRepresented);
-
461  }
-
462 
-
463  qasm_recordGate(qureg, GATE_SIGMA_Z, targetQubit);
-
464 }
-
465 
-
466 void sGate(Qureg qureg, int targetQubit) {
-
467  validateTarget(qureg, targetQubit, __func__);
-
468 
-
469  statevec_sGate(qureg, targetQubit);
-
470  if (qureg.isDensityMatrix) {
-
471  statevec_sGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
-
472  }
-
473 
-
474  qasm_recordGate(qureg, GATE_S, targetQubit);
-
475 }
-
476 
-
477 void tGate(Qureg qureg, int targetQubit) {
-
478  validateTarget(qureg, targetQubit, __func__);
-
479 
-
480  statevec_tGate(qureg, targetQubit);
-
481  if (qureg.isDensityMatrix) {
-
482  statevec_tGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
-
483  }
-
484 
-
485  qasm_recordGate(qureg, GATE_T, targetQubit);
-
486 }
-
487 
-
488 void phaseShift(Qureg qureg, int targetQubit, qreal angle) {
-
489  validateTarget(qureg, targetQubit, __func__);
-
490 
-
491  statevec_phaseShift(qureg, targetQubit, angle);
-
492  if (qureg.isDensityMatrix) {
-
493  statevec_phaseShift(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
-
494  }
-
495 
-
496  qasm_recordParamGate(qureg, GATE_PHASE_SHIFT, targetQubit, angle);
-
497 }
-
498 
-
499 void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle) {
-
500  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
-
501 
-
502  statevec_controlledPhaseShift(qureg, idQubit1, idQubit2, angle);
-
503  if (qureg.isDensityMatrix) {
-
504  int shift = qureg.numQubitsRepresented;
-
505  statevec_controlledPhaseShift(qureg, idQubit1+shift, idQubit2+shift, -angle);
-
506  }
-
507 
-
508  qasm_recordControlledParamGate(qureg, GATE_PHASE_SHIFT, idQubit1, idQubit2, angle);
-
509 }
-
510 
-
511 void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle) {
-
512  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
-
513 
-
514  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, angle);
-
515  if (qureg.isDensityMatrix) {
-
516  int shift = qureg.numQubitsRepresented;
-
517  shiftIndices(controlQubits, numControlQubits, shift);
-
518  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, -angle);
-
519  shiftIndices(controlQubits, numControlQubits, -shift);
-
520  }
-
521 
-
522  qasm_recordMultiControlledParamGate(qureg, GATE_PHASE_SHIFT, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1], angle);
-
523 }
-
524 
-
525 void controlledNot(Qureg qureg, int controlQubit, int targetQubit) {
-
526  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
527 
-
528  statevec_controlledNot(qureg, controlQubit, targetQubit);
-
529  if (qureg.isDensityMatrix) {
-
530  int shift = qureg.numQubitsRepresented;
-
531  statevec_controlledNot(qureg, controlQubit+shift, targetQubit+shift);
-
532  }
-
533 
-
534  qasm_recordControlledGate(qureg, GATE_SIGMA_X, controlQubit, targetQubit);
-
535 }
-
536 
-
537 void multiQubitNot(Qureg qureg, int* targs, int numTargs) {
-
538  validateMultiTargets(qureg, targs, numTargs, __func__);
-
539 
-
540  long long int targMask = getQubitBitMask(targs, numTargs);
-
541  statevec_multiControlledMultiQubitNot(qureg, 0, targMask);
-
542  if (qureg.isDensityMatrix) {
-
543  int shift = qureg.numQubitsRepresented;
-
544  statevec_multiControlledMultiQubitNot(qureg, 0, targMask<<shift);
-
545  }
-
546 
-
547  qasm_recordMultiControlledMultiQubitNot(qureg, NULL, 0, targs, numTargs);
-
548 }
-
549 
-
550 void multiControlledMultiQubitNot(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs) {
-
551  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
-
552 
-
553  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
-
554  long long int targMask = getQubitBitMask(targs, numTargs);
-
555  statevec_multiControlledMultiQubitNot(qureg, ctrlMask, targMask);
-
556  if (qureg.isDensityMatrix) {
-
557  int shift = qureg.numQubitsRepresented;
-
558  statevec_multiControlledMultiQubitNot(qureg, ctrlMask<<shift, targMask<<shift);
-
559  }
-
560 
-
561  qasm_recordMultiControlledMultiQubitNot(qureg, ctrls, numCtrls, targs, numTargs);
-
562 }
-
563 
-
564 void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit) {
-
565  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
566 
-
567  statevec_controlledPauliY(qureg, controlQubit, targetQubit);
-
568  if (qureg.isDensityMatrix) {
-
569  int shift = qureg.numQubitsRepresented;
-
570  statevec_controlledPauliYConj(qureg, controlQubit+shift, targetQubit+shift);
-
571  }
-
572 
-
573  qasm_recordControlledGate(qureg, GATE_SIGMA_Y, controlQubit, targetQubit);
-
574 }
-
575 
-
576 void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2) {
-
577  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
-
578 
-
579  statevec_controlledPhaseFlip(qureg, idQubit1, idQubit2);
-
580  if (qureg.isDensityMatrix) {
-
581  int shift = qureg.numQubitsRepresented;
-
582  statevec_controlledPhaseFlip(qureg, idQubit1+shift, idQubit2+shift);
-
583  }
-
584 
-
585  qasm_recordControlledGate(qureg, GATE_SIGMA_Z, idQubit1, idQubit2);
-
586 }
-
587 
-
588 void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits) {
-
589  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
-
590 
-
591  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
-
592  if (qureg.isDensityMatrix) {
-
593  int shift = qureg.numQubitsRepresented;
-
594  shiftIndices(controlQubits, numControlQubits, shift);
-
595  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
-
596  shiftIndices(controlQubits, numControlQubits, -shift);
-
597  }
-
598 
-
599  qasm_recordMultiControlledGate(qureg, GATE_SIGMA_Z, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1]);
-
600 }
-
601 
-
602 void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis) {
-
603  validateTarget(qureg, rotQubit, __func__);
-
604  validateVector(axis, __func__);
-
605 
-
606  statevec_rotateAroundAxis(qureg, rotQubit, angle, axis);
-
607  if (qureg.isDensityMatrix) {
-
608  int shift = qureg.numQubitsRepresented;
-
609  statevec_rotateAroundAxisConj(qureg, rotQubit+shift, angle, axis);
-
610  }
-
611 
-
612  qasm_recordAxisRotation(qureg, angle, axis, rotQubit);
-
613 }
-
614 
-
615 void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis) {
-
616  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
-
617  validateVector(axis, __func__);
-
618 
-
619  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, axis);
-
620  if (qureg.isDensityMatrix) {
-
621  int shift = qureg.numQubitsRepresented;
-
622  statevec_controlledRotateAroundAxisConj(qureg, controlQubit+shift, targetQubit+shift, angle, axis);
-
623  }
-
624 
-
625  qasm_recordControlledAxisRotation(qureg, angle, axis, controlQubit, targetQubit);
-
626 }
-
627 
-
628 void swapGate(Qureg qureg, int qb1, int qb2) {
-
629  validateUniqueTargets(qureg, qb1, qb2, __func__);
-
630 
-
631  statevec_swapQubitAmps(qureg, qb1, qb2);
-
632  if (qureg.isDensityMatrix) {
-
633  int shift = qureg.numQubitsRepresented;
-
634  statevec_swapQubitAmps(qureg, qb1+shift, qb2+shift);
-
635  }
-
636 
-
637  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
-
638 }
-
639 
-
640 void sqrtSwapGate(Qureg qureg, int qb1, int qb2) {
-
641  validateUniqueTargets(qureg, qb1, qb2, __func__);
-
642  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__); // uses 2qb unitary in QuEST_common
-
643 
-
644  statevec_sqrtSwapGate(qureg, qb1, qb2);
-
645  if (qureg.isDensityMatrix) {
-
646  int shift = qureg.numQubitsRepresented;
-
647  statevec_sqrtSwapGateConj(qureg, qb1+shift, qb2+shift);
-
648  }
-
649 
-
650  qasm_recordControlledGate(qureg, GATE_SQRT_SWAP, qb1, qb2);
-
651 }
-
652 
-
653 void multiRotateZ(Qureg qureg, int* qubits, int numQubits, qreal angle) {
-
654  validateMultiTargets(qureg, qubits, numQubits, __func__);
-
655 
-
656  long long int mask = getQubitBitMask(qubits, numQubits);
-
657  statevec_multiRotateZ(qureg, mask, angle);
-
658  if (qureg.isDensityMatrix) {
-
659  int shift = qureg.numQubitsRepresented;
-
660  statevec_multiRotateZ(qureg, mask << shift, -angle);
-
661  }
-
662 
-
663  // @TODO: create actual QASM
-
664  qasm_recordComment(qureg,
-
665  "Here a %d-qubit multiRotateZ of angle %g was performed (QASM not yet implemented)",
-
666  numQubits, angle);
-
667 }
-
668 
-
669 void multiControlledMultiRotateZ(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, int numTargets, qreal angle) {
-
670  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
-
671 
-
672  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
-
673  long long int targMask = getQubitBitMask(targetQubits, numTargets);
-
674  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, angle);
-
675  if (qureg.isDensityMatrix) {
-
676  int shift = qureg.numQubitsRepresented;
-
677  statevec_multiControlledMultiRotateZ(qureg, ctrlMask<<shift, targMask<<shift, - angle);
-
678  }
-
679 
-
680  // @TODO: create actual QASM
-
681  qasm_recordComment(qureg,
-
682  "Here a %d-control %d-target multiControlledMultiRotateZ of angle %g was performed (QASM not yet implemented)",
-
683  numControls, numTargets, angle);
-
684 }
-
685 
-
686 void multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle) {
-
687  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
-
688  validatePauliCodes(targetPaulis, numTargets, __func__);
-
689 
-
690  int conj=0;
-
691  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
-
692  if (qureg.isDensityMatrix) {
-
693  conj = 1;
-
694  int shift = qureg.numQubitsRepresented;
-
695  shiftIndices(targetQubits, numTargets, shift);
-
696  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
-
697  shiftIndices(targetQubits, numTargets, -shift);
-
698  }
-
699 
-
700  // @TODO: create actual QASM
-
701  qasm_recordComment(qureg,
-
702  "Here a %d-qubit multiRotatePauli of angle %g was performed (QASM not yet implemented)",
-
703  numTargets, angle);
-
704 }
-
705 
-
706 void multiControlledMultiRotatePauli(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle) {
-
707  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
-
708  validatePauliCodes(targetPaulis, numTargets, __func__);
-
709 
-
710  int conj=0;
-
711  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
-
712  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask, targetQubits, targetPaulis, numTargets, angle, conj);
-
713  if (qureg.isDensityMatrix) {
-
714  conj = 1;
-
715  int shift = qureg.numQubitsRepresented;
-
716  shiftIndices(targetQubits, numTargets, shift);
-
717  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask<<shift, targetQubits, targetPaulis, numTargets, angle, conj);
-
718  shiftIndices(targetQubits, numTargets, -shift);
-
719  }
-
720 
-
721  // @TODO: create actual QASM
-
722  qasm_recordComment(qureg,
-
723  "Here a %d-control %d-target multiControlledMultiRotatePauli of angle %g was performed (QASM not yet implemented)",
-
724  numControls, numTargets, angle);
-
725 }
-
726 
-
727 void applyPhaseFunc(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms) {
-
728  validateMultiQubits(qureg, qubits, numQubits, __func__);
-
729  validateBitEncoding(numQubits, encoding, __func__);
-
730  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, NULL, 0, __func__);
-
731 
-
732  int conj = 0;
-
733  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
-
734  if (qureg.isDensityMatrix) {
-
735  conj = 1;
-
736  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
-
737  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
-
738  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
-
739  }
-
740 
-
741  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0);
-
742 }
-
743 
-
744 void applyPhaseFuncOverrides(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
-
745  validateMultiQubits(qureg, qubits, numQubits, __func__);
-
746  validateBitEncoding(numQubits, encoding, __func__);
-
747  validatePhaseFuncOverrides(numQubits, encoding, overrideInds, numOverrides, __func__);
-
748  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, overrideInds, numOverrides, __func__);
-
749 
-
750  int conj = 0;
-
751  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
-
752  if (qureg.isDensityMatrix) {
-
753  conj = 1;
-
754  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
-
755  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
-
756  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
-
757  }
-
758 
-
759  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides);
-
760 }
-
761 
-
762 void applyMultiVarPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg) {
-
763  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
764  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
765  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
-
766 
-
767  int conj = 0;
-
768  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
-
769  if (qureg.isDensityMatrix) {
-
770  conj = 1;
-
771  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
772  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
-
773  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
774  }
-
775 
-
776  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0);
-
777 }
-
778 
-
779 void applyMultiVarPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
-
780  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
781  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
782  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
-
783  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
-
784 
-
785  int conj = 0;
-
786  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
-
787  if (qureg.isDensityMatrix) {
-
788  conj = 1;
-
789  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
790  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
-
791  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
792  }
-
793 
-
794  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides);
-
795 }
-
796 
-
797 void applyNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode) {
-
798  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
799  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
800  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
-
801 
-
802  int conj = 0;
-
803  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
-
804  if (qureg.isDensityMatrix) {
-
805  conj = 1;
-
806  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
807  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
-
808  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
809  }
-
810 
-
811  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0);
-
812 }
-
813 
-
814 void applyNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
-
815  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
816  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
817  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
-
818  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
-
819 
-
820  int conj = 0;
-
821  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
-
822  if (qureg.isDensityMatrix) {
-
823  conj = 1;
-
824  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
825  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
-
826  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
827  }
-
828 
-
829  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides);
-
830 }
-
831 
-
832 void applyParamNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams) {
-
833  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
834  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
835  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
-
836 
-
837  int conj = 0;
-
838  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
-
839  if (qureg.isDensityMatrix) {
-
840  conj = 1;
-
841  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
842  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
-
843  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
844  }
-
845 
-
846  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0);
-
847 }
-
848 
-
849 void applyParamNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
-
850  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
851  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
852  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
-
853  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
-
854 
-
855  int conj = 0;
-
856  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
-
857  if (qureg.isDensityMatrix) {
-
858  conj = 1;
-
859  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
860  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
-
861  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
862  }
-
863 
-
864  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides);
-
865 }
-
866 
-
867 void applyQFT(Qureg qureg, int* qubits, int numQubits) {
-
868  validateMultiTargets(qureg, qubits, numQubits, __func__);
-
869 
-
870  qasm_recordComment(qureg, "Beginning of QFT circuit");
-
871 
-
872  agnostic_applyQFT(qureg, qubits, numQubits);
-
873 
-
874  qasm_recordComment(qureg, "End of QFT circuit");
-
875 }
-
876 
-
877 void applyFullQFT(Qureg qureg) {
-
878 
-
879  qasm_recordComment(qureg, "Beginning of QFT circuit");
-
880 
-
881  int qubits[qureg.numQubitsRepresented];
-
882  for (int i=0; i<qureg.numQubitsRepresented; i++)
-
883  qubits[i] = i;
-
884  agnostic_applyQFT(qureg, qubits, qureg.numQubitsRepresented);
-
885 
-
886  qasm_recordComment(qureg, "End of QFT circuit");
-
887 }
-
888 
-
889 
-
890 
-
891 /*
-
892  * register attributes
-
893  */
-
894 
-
895 int getNumQubits(Qureg qureg) {
-
896  return qureg.numQubitsRepresented;
-
897 }
-
898 
-
899 long long int getNumAmps(Qureg qureg) {
-
900  validateStateVecQureg(qureg, __func__);
-
901 
-
902  return qureg.numAmpsTotal;
-
903 }
-
904 
-
905 qreal getRealAmp(Qureg qureg, long long int index) {
-
906  validateStateVecQureg(qureg, __func__);
-
907  validateAmpIndex(qureg, index, __func__);
-
908 
-
909  return statevec_getRealAmp(qureg, index);
+
172 /*
+
173  * unitary gates
+
174  */
+
175 
+
176 void hadamard(Qureg qureg, int targetQubit) {
+
177  validateTarget(qureg, targetQubit, __func__);
+
178 
+
179  statevec_hadamard(qureg, targetQubit);
+
180  if (qureg.isDensityMatrix) {
+
181  statevec_hadamard(qureg, targetQubit+qureg.numQubitsRepresented);
+
182  }
+
183 
+
184  qasm_recordGate(qureg, GATE_HADAMARD, targetQubit);
+
185 }
+
186 
+
187 void rotateX(Qureg qureg, int targetQubit, qreal angle) {
+
188  validateTarget(qureg, targetQubit, __func__);
+
189 
+
190  statevec_rotateX(qureg, targetQubit, angle);
+
191  if (qureg.isDensityMatrix) {
+
192  statevec_rotateX(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
+
193  }
+
194 
+
195  qasm_recordParamGate(qureg, GATE_ROTATE_X, targetQubit, angle);
+
196 }
+
197 
+
198 void rotateY(Qureg qureg, int targetQubit, qreal angle) {
+
199  validateTarget(qureg, targetQubit, __func__);
+
200 
+
201  statevec_rotateY(qureg, targetQubit, angle);
+
202  if (qureg.isDensityMatrix) {
+
203  statevec_rotateY(qureg, targetQubit+qureg.numQubitsRepresented, angle);
+
204  }
+
205 
+
206  qasm_recordParamGate(qureg, GATE_ROTATE_Y, targetQubit, angle);
+
207 }
+
208 
+
209 void rotateZ(Qureg qureg, int targetQubit, qreal angle) {
+
210  validateTarget(qureg, targetQubit, __func__);
+
211 
+
212  statevec_rotateZ(qureg, targetQubit, angle);
+
213  if (qureg.isDensityMatrix) {
+
214  statevec_rotateZ(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
+
215  }
+
216 
+
217  qasm_recordParamGate(qureg, GATE_ROTATE_Z, targetQubit, angle);
+
218 }
+
219 
+
220 void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
+
221  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
222 
+
223  statevec_controlledRotateX(qureg, controlQubit, targetQubit, angle);
+
224  if (qureg.isDensityMatrix) {
+
225  int shift = qureg.numQubitsRepresented;
+
226  statevec_controlledRotateX(qureg, controlQubit+shift, targetQubit+shift, -angle);
+
227  }
+
228 
+
229  qasm_recordControlledParamGate(qureg, GATE_ROTATE_X, controlQubit, targetQubit, angle);
+
230 }
+
231 
+
232 void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
+
233  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
234 
+
235  statevec_controlledRotateY(qureg, controlQubit, targetQubit, angle);
+
236  if (qureg.isDensityMatrix) {
+
237  int shift = qureg.numQubitsRepresented;
+
238  statevec_controlledRotateY(qureg, controlQubit+shift, targetQubit+shift, angle); // rotateY is real
+
239  }
+
240 
+
241  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Y, controlQubit, targetQubit, angle);
+
242 }
+
243 
+
244 void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle) {
+
245  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
246 
+
247  statevec_controlledRotateZ(qureg, controlQubit, targetQubit, angle);
+
248  if (qureg.isDensityMatrix) {
+
249  int shift = qureg.numQubitsRepresented;
+
250  statevec_controlledRotateZ(qureg, controlQubit+shift, targetQubit+shift, -angle);
+
251  }
+
252 
+
253  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Z, controlQubit, targetQubit, angle);
+
254 }
+
255 
+
256 void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
+
257  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
+
258  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
+
259 
+
260  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
+
261  if (qureg.isDensityMatrix) {
+
262  int shift = qureg.numQubitsRepresented;
+
263  statevec_twoQubitUnitary(qureg, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
+
264  }
+
265 
+
266  qasm_recordComment(qureg, "Here, an undisclosed 2-qubit unitary was applied.");
+
267 }
+
268 
+
269 void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
+
270  validateMultiControlsMultiTargets(qureg, (int[]) {controlQubit}, 1, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
+
271  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
+
272 
+
273  statevec_controlledTwoQubitUnitary(qureg, controlQubit, targetQubit1, targetQubit2, u);
+
274  if (qureg.isDensityMatrix) {
+
275  int shift = qureg.numQubitsRepresented;
+
276  statevec_controlledTwoQubitUnitary(qureg, controlQubit+shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
+
277  }
+
278 
+
279  qasm_recordComment(qureg, "Here, an undisclosed controlled 2-qubit unitary was applied.");
+
280 }
+
281 
+
282 void multiControlledTwoQubitUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
+
283  validateMultiControlsMultiTargets(qureg, controlQubits, numControlQubits, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
+
284  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
+
285 
+
286  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
+
287  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask, targetQubit1, targetQubit2, u);
+
288  if (qureg.isDensityMatrix) {
+
289  int shift = qureg.numQubitsRepresented;
+
290  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask<<shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
+
291  }
+
292 
+
293  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled 2-qubit unitary was applied.");
+
294 }
+
295 
+
296 void multiQubitUnitary(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u) {
+
297  validateMultiTargets(qureg, targs, numTargs, __func__);
+
298  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
+
299 
+
300  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
+
301  if (qureg.isDensityMatrix) {
+
302  int shift = qureg.numQubitsRepresented;
+
303  shiftIndices(targs, numTargs, shift);
+ +
305  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
+
306  shiftIndices(targs, numTargs, -shift);
+ +
308  }
+
309 
+
310  qasm_recordComment(qureg, "Here, an undisclosed multi-qubit unitary was applied.");
+
311 }
+
312 
+
313 void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targs, int numTargs, ComplexMatrixN u) {
+
314  validateMultiControlsMultiTargets(qureg, (int[]) {ctrl}, 1, targs, numTargs, __func__);
+
315  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
+
316 
+
317  statevec_controlledMultiQubitUnitary(qureg, ctrl, targs, numTargs, u);
+
318  if (qureg.isDensityMatrix) {
+
319  int shift = qureg.numQubitsRepresented;
+
320  shiftIndices(targs, numTargs, shift);
+ +
322  statevec_controlledMultiQubitUnitary(qureg, ctrl+shift, targs, numTargs, u);
+
323  shiftIndices(targs, numTargs, -shift);
+ +
325  }
+
326 
+
327  qasm_recordComment(qureg, "Here, an undisclosed controlled multi-qubit unitary was applied.");
+
328 }
+
329 
+
330 void multiControlledMultiQubitUnitary(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u) {
+
331  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
+
332  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
+
333 
+
334  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
+
335  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
+
336  if (qureg.isDensityMatrix) {
+
337  int shift = qureg.numQubitsRepresented;
+
338  shiftIndices(targs, numTargs, shift);
+ +
340  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask<<shift, targs, numTargs, u);
+
341  shiftIndices(targs, numTargs, -shift);
+ +
343  }
+
344 
+
345  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled multi-qubit unitary was applied.");
+
346 }
+
347 
+
348 void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u) {
+
349  validateTarget(qureg, targetQubit, __func__);
+
350  validateOneQubitUnitaryMatrix(u, __func__);
+
351 
+
352  statevec_unitary(qureg, targetQubit, u);
+
353  if (qureg.isDensityMatrix) {
+
354  statevec_unitary(qureg, targetQubit+qureg.numQubitsRepresented, getConjugateMatrix2(u));
+
355  }
+
356 
+
357  qasm_recordUnitary(qureg, u, targetQubit);
+
358 }
+
359 
+
360 void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u) {
+
361  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
362  validateOneQubitUnitaryMatrix(u, __func__);
+
363 
+
364  statevec_controlledUnitary(qureg, controlQubit, targetQubit, u);
+
365  if (qureg.isDensityMatrix) {
+
366  int shift = qureg.numQubitsRepresented;
+
367  statevec_controlledUnitary(qureg, controlQubit+shift, targetQubit+shift, getConjugateMatrix2(u));
+
368  }
+
369 
+
370  qasm_recordControlledUnitary(qureg, u, controlQubit, targetQubit);
+
371 }
+
372 
+
373 void multiControlledUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u) {
+
374  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
+
375  validateOneQubitUnitaryMatrix(u, __func__);
+
376 
+
377  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
+
378  long long int ctrlFlipMask = 0;
+
379  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
+
380  if (qureg.isDensityMatrix) {
+
381  int shift = qureg.numQubitsRepresented;
+
382  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
+
383  }
+
384 
+
385  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
+
386 }
+
387 
+
388 void multiStateControlledUnitary(Qureg qureg, int* controlQubits, int* controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u) {
+
389  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
+
390  validateOneQubitUnitaryMatrix(u, __func__);
+
391  validateControlState(controlState, numControlQubits, __func__);
+
392 
+
393  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
+
394  long long int ctrlFlipMask = getControlFlipMask(controlQubits, controlState, numControlQubits);
+
395  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
+
396  if (qureg.isDensityMatrix) {
+
397  int shift = qureg.numQubitsRepresented;
+
398  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
+
399  }
+
400 
+
401  qasm_recordMultiStateControlledUnitary(qureg, u, controlQubits, controlState, numControlQubits, targetQubit);
+
402 }
+
403 
+
404 void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta) {
+
405  validateTarget(qureg, targetQubit, __func__);
+
406  validateUnitaryComplexPair(alpha, beta, __func__);
+
407 
+
408  statevec_compactUnitary(qureg, targetQubit, alpha, beta);
+
409  if (qureg.isDensityMatrix) {
+
410  int shift = qureg.numQubitsRepresented;
+
411  statevec_compactUnitary(qureg, targetQubit+shift, getConjugateScalar(alpha), getConjugateScalar(beta));
+
412  }
+
413 
+
414  qasm_recordCompactUnitary(qureg, alpha, beta, targetQubit);
+
415 }
+
416 
+
417 void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta) {
+
418  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
419  validateUnitaryComplexPair(alpha, beta, __func__);
+
420 
+
421  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
422  if (qureg.isDensityMatrix) {
+
423  int shift = qureg.numQubitsRepresented;
+ +
425  controlQubit+shift, targetQubit+shift,
+
426  getConjugateScalar(alpha), getConjugateScalar(beta));
+
427  }
+
428 
+
429  qasm_recordControlledCompactUnitary(qureg, alpha, beta, controlQubit, targetQubit);
+
430 }
+
431 
+
432 void pauliX(Qureg qureg, int targetQubit) {
+
433  validateTarget(qureg, targetQubit, __func__);
+
434 
+
435  statevec_pauliX(qureg, targetQubit);
+
436  if (qureg.isDensityMatrix) {
+
437  statevec_pauliX(qureg, targetQubit+qureg.numQubitsRepresented);
+
438  }
+
439 
+
440  qasm_recordGate(qureg, GATE_SIGMA_X, targetQubit);
+
441 }
+
442 
+
443 void pauliY(Qureg qureg, int targetQubit) {
+
444  validateTarget(qureg, targetQubit, __func__);
+
445 
+
446  statevec_pauliY(qureg, targetQubit);
+
447  if (qureg.isDensityMatrix) {
+
448  statevec_pauliYConj(qureg, targetQubit + qureg.numQubitsRepresented);
+
449  }
+
450 
+
451  qasm_recordGate(qureg, GATE_SIGMA_Y, targetQubit);
+
452 }
+
453 
+
454 void pauliZ(Qureg qureg, int targetQubit) {
+
455  validateTarget(qureg, targetQubit, __func__);
+
456 
+
457  statevec_pauliZ(qureg, targetQubit);
+
458  if (qureg.isDensityMatrix) {
+
459  statevec_pauliZ(qureg, targetQubit+qureg.numQubitsRepresented);
+
460  }
+
461 
+
462  qasm_recordGate(qureg, GATE_SIGMA_Z, targetQubit);
+
463 }
+
464 
+
465 void sGate(Qureg qureg, int targetQubit) {
+
466  validateTarget(qureg, targetQubit, __func__);
+
467 
+
468  statevec_sGate(qureg, targetQubit);
+
469  if (qureg.isDensityMatrix) {
+
470  statevec_sGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
+
471  }
+
472 
+
473  qasm_recordGate(qureg, GATE_S, targetQubit);
+
474 }
+
475 
+
476 void tGate(Qureg qureg, int targetQubit) {
+
477  validateTarget(qureg, targetQubit, __func__);
+
478 
+
479  statevec_tGate(qureg, targetQubit);
+
480  if (qureg.isDensityMatrix) {
+
481  statevec_tGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
+
482  }
+
483 
+
484  qasm_recordGate(qureg, GATE_T, targetQubit);
+
485 }
+
486 
+
487 void phaseShift(Qureg qureg, int targetQubit, qreal angle) {
+
488  validateTarget(qureg, targetQubit, __func__);
+
489 
+
490  statevec_phaseShift(qureg, targetQubit, angle);
+
491  if (qureg.isDensityMatrix) {
+
492  statevec_phaseShift(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
+
493  }
+
494 
+
495  qasm_recordParamGate(qureg, GATE_PHASE_SHIFT, targetQubit, angle);
+
496 }
+
497 
+
498 void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle) {
+
499  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
+
500 
+
501  statevec_controlledPhaseShift(qureg, idQubit1, idQubit2, angle);
+
502  if (qureg.isDensityMatrix) {
+
503  int shift = qureg.numQubitsRepresented;
+
504  statevec_controlledPhaseShift(qureg, idQubit1+shift, idQubit2+shift, -angle);
+
505  }
+
506 
+
507  qasm_recordControlledParamGate(qureg, GATE_PHASE_SHIFT, idQubit1, idQubit2, angle);
+
508 }
+
509 
+
510 void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle) {
+
511  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
+
512 
+
513  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, angle);
+
514  if (qureg.isDensityMatrix) {
+
515  int shift = qureg.numQubitsRepresented;
+
516  shiftIndices(controlQubits, numControlQubits, shift);
+
517  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, -angle);
+
518  shiftIndices(controlQubits, numControlQubits, -shift);
+
519  }
+
520 
+
521  qasm_recordMultiControlledParamGate(qureg, GATE_PHASE_SHIFT, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1], angle);
+
522 }
+
523 
+
524 void controlledNot(Qureg qureg, int controlQubit, int targetQubit) {
+
525  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
526 
+
527  statevec_controlledNot(qureg, controlQubit, targetQubit);
+
528  if (qureg.isDensityMatrix) {
+
529  int shift = qureg.numQubitsRepresented;
+
530  statevec_controlledNot(qureg, controlQubit+shift, targetQubit+shift);
+
531  }
+
532 
+
533  qasm_recordControlledGate(qureg, GATE_SIGMA_X, controlQubit, targetQubit);
+
534 }
+
535 
+
536 void multiQubitNot(Qureg qureg, int* targs, int numTargs) {
+
537  validateMultiTargets(qureg, targs, numTargs, __func__);
+
538 
+
539  long long int targMask = getQubitBitMask(targs, numTargs);
+
540  statevec_multiControlledMultiQubitNot(qureg, 0, targMask);
+
541  if (qureg.isDensityMatrix) {
+
542  int shift = qureg.numQubitsRepresented;
+
543  statevec_multiControlledMultiQubitNot(qureg, 0, targMask<<shift);
+
544  }
+
545 
+
546  qasm_recordMultiControlledMultiQubitNot(qureg, NULL, 0, targs, numTargs);
+
547 }
+
548 
+
549 void multiControlledMultiQubitNot(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs) {
+
550  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
+
551 
+
552  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
+
553  long long int targMask = getQubitBitMask(targs, numTargs);
+
554  statevec_multiControlledMultiQubitNot(qureg, ctrlMask, targMask);
+
555  if (qureg.isDensityMatrix) {
+
556  int shift = qureg.numQubitsRepresented;
+
557  statevec_multiControlledMultiQubitNot(qureg, ctrlMask<<shift, targMask<<shift);
+
558  }
+
559 
+
560  qasm_recordMultiControlledMultiQubitNot(qureg, ctrls, numCtrls, targs, numTargs);
+
561 }
+
562 
+
563 void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit) {
+
564  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
565 
+
566  statevec_controlledPauliY(qureg, controlQubit, targetQubit);
+
567  if (qureg.isDensityMatrix) {
+
568  int shift = qureg.numQubitsRepresented;
+
569  statevec_controlledPauliYConj(qureg, controlQubit+shift, targetQubit+shift);
+
570  }
+
571 
+
572  qasm_recordControlledGate(qureg, GATE_SIGMA_Y, controlQubit, targetQubit);
+
573 }
+
574 
+
575 void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2) {
+
576  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
+
577 
+
578  statevec_controlledPhaseFlip(qureg, idQubit1, idQubit2);
+
579  if (qureg.isDensityMatrix) {
+
580  int shift = qureg.numQubitsRepresented;
+
581  statevec_controlledPhaseFlip(qureg, idQubit1+shift, idQubit2+shift);
+
582  }
+
583 
+
584  qasm_recordControlledGate(qureg, GATE_SIGMA_Z, idQubit1, idQubit2);
+
585 }
+
586 
+
587 void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits) {
+
588  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
+
589 
+
590  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
+
591  if (qureg.isDensityMatrix) {
+
592  int shift = qureg.numQubitsRepresented;
+
593  shiftIndices(controlQubits, numControlQubits, shift);
+
594  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
+
595  shiftIndices(controlQubits, numControlQubits, -shift);
+
596  }
+
597 
+
598  qasm_recordMultiControlledGate(qureg, GATE_SIGMA_Z, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1]);
+
599 }
+
600 
+
601 void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis) {
+
602  validateTarget(qureg, rotQubit, __func__);
+
603  validateVector(axis, __func__);
+
604 
+
605  statevec_rotateAroundAxis(qureg, rotQubit, angle, axis);
+
606  if (qureg.isDensityMatrix) {
+
607  int shift = qureg.numQubitsRepresented;
+
608  statevec_rotateAroundAxisConj(qureg, rotQubit+shift, angle, axis);
+
609  }
+
610 
+
611  qasm_recordAxisRotation(qureg, angle, axis, rotQubit);
+
612 }
+
613 
+
614 void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis) {
+
615  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
+
616  validateVector(axis, __func__);
+
617 
+
618  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, axis);
+
619  if (qureg.isDensityMatrix) {
+
620  int shift = qureg.numQubitsRepresented;
+
621  statevec_controlledRotateAroundAxisConj(qureg, controlQubit+shift, targetQubit+shift, angle, axis);
+
622  }
+
623 
+
624  qasm_recordControlledAxisRotation(qureg, angle, axis, controlQubit, targetQubit);
+
625 }
+
626 
+
627 void swapGate(Qureg qureg, int qb1, int qb2) {
+
628  validateUniqueTargets(qureg, qb1, qb2, __func__);
+
629 
+
630  statevec_swapQubitAmps(qureg, qb1, qb2);
+
631  if (qureg.isDensityMatrix) {
+
632  int shift = qureg.numQubitsRepresented;
+
633  statevec_swapQubitAmps(qureg, qb1+shift, qb2+shift);
+
634  }
+
635 
+
636  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
+
637 }
+
638 
+
639 void sqrtSwapGate(Qureg qureg, int qb1, int qb2) {
+
640  validateUniqueTargets(qureg, qb1, qb2, __func__);
+
641  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__); // uses 2qb unitary in QuEST_common
+
642 
+
643  statevec_sqrtSwapGate(qureg, qb1, qb2);
+
644  if (qureg.isDensityMatrix) {
+
645  int shift = qureg.numQubitsRepresented;
+
646  statevec_sqrtSwapGateConj(qureg, qb1+shift, qb2+shift);
+
647  }
+
648 
+
649  qasm_recordControlledGate(qureg, GATE_SQRT_SWAP, qb1, qb2);
+
650 }
+
651 
+
652 void multiRotateZ(Qureg qureg, int* qubits, int numQubits, qreal angle) {
+
653  validateMultiTargets(qureg, qubits, numQubits, __func__);
+
654 
+
655  long long int mask = getQubitBitMask(qubits, numQubits);
+
656  statevec_multiRotateZ(qureg, mask, angle);
+
657  if (qureg.isDensityMatrix) {
+
658  int shift = qureg.numQubitsRepresented;
+
659  statevec_multiRotateZ(qureg, mask << shift, -angle);
+
660  }
+
661 
+
662  // @TODO: create actual QASM
+
663  qasm_recordComment(qureg,
+
664  "Here a %d-qubit multiRotateZ of angle %g was performed (QASM not yet implemented)",
+
665  numQubits, angle);
+
666 }
+
667 
+
668 void multiControlledMultiRotateZ(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, int numTargets, qreal angle) {
+
669  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
+
670 
+
671  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
+
672  long long int targMask = getQubitBitMask(targetQubits, numTargets);
+
673  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, angle);
+
674  if (qureg.isDensityMatrix) {
+
675  int shift = qureg.numQubitsRepresented;
+
676  statevec_multiControlledMultiRotateZ(qureg, ctrlMask<<shift, targMask<<shift, - angle);
+
677  }
+
678 
+
679  // @TODO: create actual QASM
+
680  qasm_recordComment(qureg,
+
681  "Here a %d-control %d-target multiControlledMultiRotateZ of angle %g was performed (QASM not yet implemented)",
+
682  numControls, numTargets, angle);
+
683 }
+
684 
+
685 void multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle) {
+
686  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
+
687  validatePauliCodes(targetPaulis, numTargets, __func__);
+
688 
+
689  int conj=0;
+
690  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
+
691  if (qureg.isDensityMatrix) {
+
692  conj = 1;
+
693  int shift = qureg.numQubitsRepresented;
+
694  shiftIndices(targetQubits, numTargets, shift);
+
695  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
+
696  shiftIndices(targetQubits, numTargets, -shift);
+
697  }
+
698 
+
699  // @TODO: create actual QASM
+
700  qasm_recordComment(qureg,
+
701  "Here a %d-qubit multiRotatePauli of angle %g was performed (QASM not yet implemented)",
+
702  numTargets, angle);
+
703 }
+
704 
+
705 void multiControlledMultiRotatePauli(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle) {
+
706  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
+
707  validatePauliCodes(targetPaulis, numTargets, __func__);
+
708 
+
709  int conj=0;
+
710  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
+
711  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask, targetQubits, targetPaulis, numTargets, angle, conj);
+
712  if (qureg.isDensityMatrix) {
+
713  conj = 1;
+
714  int shift = qureg.numQubitsRepresented;
+
715  shiftIndices(targetQubits, numTargets, shift);
+
716  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask<<shift, targetQubits, targetPaulis, numTargets, angle, conj);
+
717  shiftIndices(targetQubits, numTargets, -shift);
+
718  }
+
719 
+
720  // @TODO: create actual QASM
+
721  qasm_recordComment(qureg,
+
722  "Here a %d-control %d-target multiControlledMultiRotatePauli of angle %g was performed (QASM not yet implemented)",
+
723  numControls, numTargets, angle);
+
724 }
+
725 
+
726 void applyPhaseFunc(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms) {
+
727  validateMultiQubits(qureg, qubits, numQubits, __func__);
+
728  validateBitEncoding(numQubits, encoding, __func__);
+
729  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, NULL, 0, __func__);
+
730 
+
731  int conj = 0;
+
732  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
+
733  if (qureg.isDensityMatrix) {
+
734  conj = 1;
+
735  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
+
736  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
+
737  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
+
738  }
+
739 
+
740  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0);
+
741 }
+
742 
+
743 void applyPhaseFuncOverrides(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
+
744  validateMultiQubits(qureg, qubits, numQubits, __func__);
+
745  validateBitEncoding(numQubits, encoding, __func__);
+
746  validatePhaseFuncOverrides(numQubits, encoding, overrideInds, numOverrides, __func__);
+
747  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, overrideInds, numOverrides, __func__);
+
748 
+
749  int conj = 0;
+
750  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
+
751  if (qureg.isDensityMatrix) {
+
752  conj = 1;
+
753  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
+
754  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
+
755  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
+
756  }
+
757 
+
758  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides);
+
759 }
+
760 
+
761 void applyMultiVarPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg) {
+
762  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
763  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
764  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
+
765 
+
766  int conj = 0;
+
767  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
+
768  if (qureg.isDensityMatrix) {
+
769  conj = 1;
+
770  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
771  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
+
772  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
773  }
+
774 
+
775  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0);
+
776 }
+
777 
+
778 void applyMultiVarPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
+
779  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
780  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
781  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
+
782  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
+
783 
+
784  int conj = 0;
+
785  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
+
786  if (qureg.isDensityMatrix) {
+
787  conj = 1;
+
788  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
789  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
+
790  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
791  }
+
792 
+
793  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides);
+
794 }
+
795 
+
796 void applyNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode) {
+
797  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
798  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
799  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
+
800 
+
801  int conj = 0;
+
802  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
+
803  if (qureg.isDensityMatrix) {
+
804  conj = 1;
+
805  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
806  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
+
807  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
808  }
+
809 
+
810  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0);
+
811 }
+
812 
+
813 void applyNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
+
814  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
815  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
816  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
+
817  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
+
818 
+
819  int conj = 0;
+
820  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
+
821  if (qureg.isDensityMatrix) {
+
822  conj = 1;
+
823  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
824  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
+
825  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
826  }
+
827 
+
828  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides);
+
829 }
+
830 
+
831 void applyParamNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams) {
+
832  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
833  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
834  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
+
835 
+
836  int conj = 0;
+
837  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
+
838  if (qureg.isDensityMatrix) {
+
839  conj = 1;
+
840  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
841  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
+
842  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
843  }
+
844 
+
845  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0);
+
846 }
+
847 
+
848 void applyParamNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams, long long int* overrideInds, qreal* overridePhases, int numOverrides) {
+
849  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
850  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
851  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
+
852  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
+
853 
+
854  int conj = 0;
+
855  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
+
856  if (qureg.isDensityMatrix) {
+
857  conj = 1;
+
858  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
859  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
+
860  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
861  }
+
862 
+
863  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides);
+
864 }
+
865 
+
866 void applyQFT(Qureg qureg, int* qubits, int numQubits) {
+
867  validateMultiTargets(qureg, qubits, numQubits, __func__);
+
868 
+
869  qasm_recordComment(qureg, "Beginning of QFT circuit");
+
870 
+
871  agnostic_applyQFT(qureg, qubits, numQubits);
+
872 
+
873  qasm_recordComment(qureg, "End of QFT circuit");
+
874 }
+
875 
+
876 void applyFullQFT(Qureg qureg) {
+
877 
+
878  qasm_recordComment(qureg, "Beginning of QFT circuit");
+
879 
+
880  int qubits[100];
+
881  for (int i=0; i<qureg.numQubitsRepresented; i++)
+
882  qubits[i] = i;
+
883  agnostic_applyQFT(qureg, qubits, qureg.numQubitsRepresented);
+
884 
+
885  qasm_recordComment(qureg, "End of QFT circuit");
+
886 }
+
887 
+
888 void applyProjector(Qureg qureg, int qubit, int outcome) {
+
889  validateTarget(qureg, qubit, __func__);
+
890  validateOutcome(outcome, __func__);
+
891 
+
892  qreal renorm = 1;
+
893 
+
894  if (qureg.isDensityMatrix)
+
895  densmatr_collapseToKnownProbOutcome(qureg, qubit, outcome, renorm);
+
896  else
+
897  statevec_collapseToKnownProbOutcome(qureg, qubit, outcome, renorm);
+
898 
+
899  qasm_recordComment(qureg, "Here, qubit %d was un-physically projected into outcome %d", qubit, outcome);
+
900 }
+
901 
+
902 
+
903 
+
904 /*
+
905  * register attributes
+
906  */
+
907 
+
908 int getNumQubits(Qureg qureg) {
+
909  return qureg.numQubitsRepresented;
910 }
911 
-
912 qreal getImagAmp(Qureg qureg, long long int index) {
+
912 long long int getNumAmps(Qureg qureg) {
913  validateStateVecQureg(qureg, __func__);
-
914  validateAmpIndex(qureg, index, __func__);
-
915 
-
916  return statevec_getImagAmp(qureg, index);
-
917 }
-
918 
-
919 qreal getProbAmp(Qureg qureg, long long int index) {
-
920  validateStateVecQureg(qureg, __func__);
-
921  validateAmpIndex(qureg, index, __func__);
-
922 
-
923  return statevec_getProbAmp(qureg, index);
-
924 }
-
925 
-
926 Complex getAmp(Qureg qureg, long long int index) {
-
927  validateStateVecQureg(qureg, __func__);
-
928  validateAmpIndex(qureg, index, __func__);
-
929 
-
930  Complex amp;
-
931  amp.real = statevec_getRealAmp(qureg, index);
-
932  amp.imag = statevec_getImagAmp(qureg, index);
-
933  return amp;
-
934 }
-
935 
-
936 Complex getDensityAmp(Qureg qureg, long long int row, long long int col) {
-
937  validateDensityMatrQureg(qureg, __func__);
-
938  validateAmpIndex(qureg, row, __func__);
-
939  validateAmpIndex(qureg, col, __func__);
-
940 
-
941  long long ind = row + col*(1LL << qureg.numQubitsRepresented);
-
942  Complex amp;
-
943  amp.real = statevec_getRealAmp(qureg, ind);
-
944  amp.imag = statevec_getImagAmp(qureg, ind);
-
945  return amp;
-
946 }
-
947 
+
914 
+
915  return qureg.numAmpsTotal;
+
916 }
+
917 
+
918 qreal getRealAmp(Qureg qureg, long long int index) {
+
919  validateStateVecQureg(qureg, __func__);
+
920  validateAmpIndex(qureg, index, __func__);
+
921 
+
922  return statevec_getRealAmp(qureg, index);
+
923 }
+
924 
+
925 qreal getImagAmp(Qureg qureg, long long int index) {
+
926  validateStateVecQureg(qureg, __func__);
+
927  validateAmpIndex(qureg, index, __func__);
+
928 
+
929  return statevec_getImagAmp(qureg, index);
+
930 }
+
931 
+
932 qreal getProbAmp(Qureg qureg, long long int index) {
+
933  validateStateVecQureg(qureg, __func__);
+
934  validateAmpIndex(qureg, index, __func__);
+
935 
+
936  return statevec_getProbAmp(qureg, index);
+
937 }
+
938 
+
939 Complex getAmp(Qureg qureg, long long int index) {
+
940  validateStateVecQureg(qureg, __func__);
+
941  validateAmpIndex(qureg, index, __func__);
+
942 
+
943  Complex amp;
+
944  amp.real = statevec_getRealAmp(qureg, index);
+
945  amp.imag = statevec_getImagAmp(qureg, index);
+
946  return amp;
+
947 }
948 
-
949 /*
-
950  * non-unitary actions
-
951  */
-
952 
-
953 qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome) {
-
954  validateTarget(qureg, measureQubit, __func__);
-
955  validateOutcome(outcome, __func__);
-
956 
-
957  qreal outcomeProb;
-
958  if (qureg.isDensityMatrix) {
-
959  outcomeProb = densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
-
960  validateMeasurementProb(outcomeProb, __func__);
-
961  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
-
962  } else {
-
963  outcomeProb = statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
-
964  validateMeasurementProb(outcomeProb, __func__);
-
965  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
-
966  }
-
967 
-
968  qasm_recordMeasurement(qureg, measureQubit);
-
969  return outcomeProb;
-
970 }
-
971 
-
972 int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
-
973  validateTarget(qureg, measureQubit, __func__);
-
974 
-
975  int outcome;
-
976  if (qureg.isDensityMatrix)
-
977  outcome = densmatr_measureWithStats(qureg, measureQubit, outcomeProb);
-
978  else
-
979  outcome = statevec_measureWithStats(qureg, measureQubit, outcomeProb);
+
949 Complex getDensityAmp(Qureg qureg, long long int row, long long int col) {
+
950  validateDensityMatrQureg(qureg, __func__);
+
951  validateAmpIndex(qureg, row, __func__);
+
952  validateAmpIndex(qureg, col, __func__);
+
953 
+
954  long long ind = row + col*(1LL << qureg.numQubitsRepresented);
+
955  Complex amp;
+
956  amp.real = statevec_getRealAmp(qureg, ind);
+
957  amp.imag = statevec_getImagAmp(qureg, ind);
+
958  return amp;
+
959 }
+
960 
+
961 
+
962 /*
+
963  * non-unitary actions
+
964  */
+
965 
+
966 qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome) {
+
967  validateTarget(qureg, measureQubit, __func__);
+
968  validateOutcome(outcome, __func__);
+
969 
+
970  qreal outcomeProb;
+
971  if (qureg.isDensityMatrix) {
+
972  outcomeProb = densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
+
973  validateMeasurementProb(outcomeProb, __func__);
+
974  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
+
975  } else {
+
976  outcomeProb = statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
+
977  validateMeasurementProb(outcomeProb, __func__);
+
978  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
+
979  }
980 
981  qasm_recordMeasurement(qureg, measureQubit);
-
982  return outcome;
+
982  return outcomeProb;
983 }
984 
-
985 int measure(Qureg qureg, int measureQubit) {
+
985 int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
986  validateTarget(qureg, measureQubit, __func__);
-
987 
+
987 
988  int outcome;
-
989  qreal discardedProb;
-
990  if (qureg.isDensityMatrix)
-
991  outcome = densmatr_measureWithStats(qureg, measureQubit, &discardedProb);
-
992  else
-
993  outcome = statevec_measureWithStats(qureg, measureQubit, &discardedProb);
-
994 
-
995  qasm_recordMeasurement(qureg, measureQubit);
-
996  return outcome;
-
997 }
-
998 
-
999 void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
-
1000  validateDensityMatrQureg(combineQureg, __func__);
-
1001  validateDensityMatrQureg(otherQureg, __func__);
-
1002  validateMatchingQuregDims(combineQureg, otherQureg, __func__);
-
1003  validateProb(otherProb, __func__);
-
1004 
-
1005  densmatr_mixDensityMatrix(combineQureg, otherProb, otherQureg);
-
1006 }
-
1007 
-
1008 void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
-
1009  validateStateVecQureg(qureg, __func__);
-
1010  validateNumAmps(qureg, startInd, numAmps, __func__);
-
1011 
-
1012  statevec_setAmps(qureg, startInd, reals, imags, numAmps);
-
1013 
-
1014  qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
-
1015 }
-
1016 
-
1017 void setDensityAmps(Qureg qureg, qreal* reals, qreal* imags) {
-
1018  long long int numAmps = qureg.numAmpsTotal;
-
1019  statevec_setAmps(qureg, 0, reals, imags, numAmps);
-
1020 
-
1021  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
-
1022 }
-
1023 
-
1024 void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
-
1025  validateMatchingQuregTypes(qureg1, qureg2, __func__);
-
1026  validateMatchingQuregTypes(qureg1, out, __func__);
-
1027  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1028  validateMatchingQuregDims(qureg1, out, __func__);
+
989  if (qureg.isDensityMatrix)
+
990  outcome = densmatr_measureWithStats(qureg, measureQubit, outcomeProb);
+
991  else
+
992  outcome = statevec_measureWithStats(qureg, measureQubit, outcomeProb);
+
993 
+
994  qasm_recordMeasurement(qureg, measureQubit);
+
995  return outcome;
+
996 }
+
997 
+
998 int measure(Qureg qureg, int measureQubit) {
+
999  validateTarget(qureg, measureQubit, __func__);
+
1000 
+
1001  int outcome;
+
1002  qreal discardedProb;
+
1003  if (qureg.isDensityMatrix)
+
1004  outcome = densmatr_measureWithStats(qureg, measureQubit, &discardedProb);
+
1005  else
+
1006  outcome = statevec_measureWithStats(qureg, measureQubit, &discardedProb);
+
1007 
+
1008  qasm_recordMeasurement(qureg, measureQubit);
+
1009  return outcome;
+
1010 }
+
1011 
+
1012 void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
+
1013  validateDensityMatrQureg(combineQureg, __func__);
+
1014  validateDensityMatrQureg(otherQureg, __func__);
+
1015  validateMatchingQuregDims(combineQureg, otherQureg, __func__);
+
1016  validateProb(otherProb, __func__);
+
1017 
+
1018  densmatr_mixDensityMatrix(combineQureg, otherProb, otherQureg);
+
1019 }
+
1020 
+
1021 void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
+
1022  validateStateVecQureg(qureg, __func__);
+
1023  validateNumAmps(qureg, startInd, numAmps, __func__);
+
1024 
+
1025  statevec_setAmps(qureg, startInd, reals, imags, numAmps);
+
1026 
+
1027  qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
+
1028 }
1029 
-
1030  statevec_setWeightedQureg(fac1, qureg1, fac2, qureg2, facOut, out);
-
1031 
-
1032  qasm_recordComment(out, "Here, the register was modified to an undisclosed and possibly unphysical state (setWeightedQureg).");
-
1033 }
-
1034 
-
1035 void applyPauliSum(Qureg inQureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg) {
-
1036  validateMatchingQuregTypes(inQureg, outQureg, __func__);
-
1037  validateMatchingQuregDims(inQureg, outQureg, __func__);
-
1038  validateNumPauliSumTerms(numSumTerms, __func__);
-
1039  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
-
1040 
-
1041  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
-
1042 
-
1043  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
-
1044 }
-
1045 
-
1046 void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg) {
-
1047  validateMatchingQuregTypes(inQureg, outQureg, __func__);
-
1048  validateMatchingQuregDims(inQureg, outQureg, __func__);
-
1049  validatePauliHamil(hamil, __func__);
-
1050  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
-
1051 
-
1052  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
+
1030 void setDensityAmps(Qureg qureg, qreal* reals, qreal* imags) {
+
1031  long long int numAmps = qureg.numAmpsTotal;
+
1032  statevec_setAmps(qureg, 0, reals, imags, numAmps);
+
1033 
+
1034  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
+
1035 }
+
1036 
+
1037 void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
+
1038  validateMatchingQuregTypes(qureg1, qureg2, __func__);
+
1039  validateMatchingQuregTypes(qureg1, out, __func__);
+
1040  validateMatchingQuregDims(qureg1, qureg2, __func__);
+
1041  validateMatchingQuregDims(qureg1, out, __func__);
+
1042 
+
1043  statevec_setWeightedQureg(fac1, qureg1, fac2, qureg2, facOut, out);
+
1044 
+
1045  qasm_recordComment(out, "Here, the register was modified to an undisclosed and possibly unphysical state (setWeightedQureg).");
+
1046 }
+
1047 
+
1048 void applyPauliSum(Qureg inQureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg) {
+
1049  validateMatchingQuregTypes(inQureg, outQureg, __func__);
+
1050  validateMatchingQuregDims(inQureg, outQureg, __func__);
+
1051  validateNumPauliSumTerms(numSumTerms, __func__);
+
1052  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
1053 
-
1054  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
-
1055 }
-
1056 
-
1057 void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps) {
-
1058  validateTrotterParams(order, reps, __func__);
-
1059  validatePauliHamil(hamil, __func__);
-
1060  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
-
1061 
-
1062  qasm_recordComment(qureg,
-
1063  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
-
1064  time, order, reps);
-
1065 
-
1066  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
-
1067 
-
1068  qasm_recordComment(qureg, "End of Trotter circuit");
-
1069 }
-
1070 
-
1071 void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u) {
-
1072  validateTarget(qureg, targetQubit, __func__);
-
1073 
-
1074  // actually just left-multiplies any complex matrix
-
1075  statevec_unitary(qureg, targetQubit, u);
-
1076 
-
1077  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
-
1078 }
-
1079 
-
1080 void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
1081  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
-
1082  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
-
1083 
-
1084  // actually just left-multiplies any complex matrix
-
1085  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
-
1086 
-
1087  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
-
1088 }
+
1054  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
+
1055 
+
1056  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
+
1057 }
+
1058 
+
1059 void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg) {
+
1060  validateMatchingQuregTypes(inQureg, outQureg, __func__);
+
1061  validateMatchingQuregDims(inQureg, outQureg, __func__);
+
1062  validatePauliHamil(hamil, __func__);
+
1063  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
+
1064 
+
1065  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
+
1066 
+
1067  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
+
1068 }
+
1069 
+
1070 void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps) {
+
1071  validateTrotterParams(order, reps, __func__);
+
1072  validatePauliHamil(hamil, __func__);
+
1073  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
+
1074 
+
1075  qasm_recordComment(qureg,
+
1076  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
+
1077  time, order, reps);
+
1078 
+
1079  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
+
1080 
+
1081  qasm_recordComment(qureg, "End of Trotter circuit");
+
1082 }
+
1083 
+
1084 void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u) {
+
1085  validateTarget(qureg, targetQubit, __func__);
+
1086 
+
1087  // actually just left-multiplies any complex matrix
+
1088  statevec_unitary(qureg, targetQubit, u);
1089 
-
1090 void applyMatrixN(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u) {
-
1091  validateMultiTargets(qureg, targs, numTargs, __func__);
-
1092  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
-
1093 
-
1094  // actually just left-multiplies any complex matrix
-
1095  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
+
1090  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
+
1091 }
+
1092 
+
1093 void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
+
1094  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
+
1095  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
1096 
-
1097  int dim = (1 << numTargs);
-
1098  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
-
1099 }
-
1100 
-
1101 void applyMultiControlledMatrixN(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u) {
-
1102  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
-
1103  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
-
1104 
-
1105  // actually just left-multiplies any complex matrix
-
1106  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
-
1107  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
-
1108 
-
1109  int numTot = numTargs + numCtrls;
-
1110  int dim = (1 << numTot );
-
1111  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
+
1097  // actually just left-multiplies any complex matrix
+
1098  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
+
1099 
+
1100  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
+
1101 }
+
1102 
+
1103 void applyMatrixN(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u) {
+
1104  validateMultiTargets(qureg, targs, numTargs, __func__);
+
1105  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
+
1106 
+
1107  // actually just left-multiplies any complex matrix
+
1108  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
+
1109 
+
1110  int dim = (1 << numTargs);
+
1111  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
1112 }
1113 
- -
1115  validateDiagonalOp(qureg, op, __func__);
-
1116 
-
1117  if (qureg.isDensityMatrix)
-
1118  densmatr_applyDiagonalOp(qureg, op);
-
1119  else
-
1120  statevec_applyDiagonalOp(qureg, op);
-
1121 
-
1122  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
-
1123 }
-
1124 
-
1125 
-
1126 /*
-
1127  * calculations
-
1128  */
+
1114 void applyMultiControlledMatrixN(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u) {
+
1115  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
+
1116  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
+
1117 
+
1118  // actually just left-multiplies any complex matrix
+
1119  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
+
1120  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
+
1121 
+
1122  int numTot = numTargs + numCtrls;
+
1123  int dim = (1 << numTot );
+
1124  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
+
1125 }
+
1126 
+ +
1128  validateDiagonalOp(qureg, op, __func__);
1129 
- -
1131  if (qureg.isDensityMatrix)
-
1132  return densmatr_calcTotalProb(qureg);
-
1133  else
-
1134  return statevec_calcTotalProb(qureg);
-
1135 }
-
1136 
- -
1138  validateStateVecQureg(bra, __func__);
-
1139  validateStateVecQureg(ket, __func__);
-
1140  validateMatchingQuregDims(bra, ket, __func__);
-
1141 
-
1142  return statevec_calcInnerProduct(bra, ket);
-
1143 }
-
1144 
- -
1146  validateDensityMatrQureg(rho1, __func__);
-
1147  validateDensityMatrQureg(rho2, __func__);
-
1148  validateMatchingQuregDims(rho1, rho2, __func__);
-
1149 
-
1150  return densmatr_calcInnerProduct(rho1, rho2);
-
1151 }
-
1152 
-
1153 qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
-
1154  validateTarget(qureg, measureQubit, __func__);
-
1155  validateOutcome(outcome, __func__);
-
1156 
-
1157  if (qureg.isDensityMatrix)
-
1158  return densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
-
1159  else
-
1160  return statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
-
1161 }
-
1162 
-
1163 void calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
-
1164  validateMultiTargets(qureg, qubits, numQubits, __func__);
+
1130  if (qureg.isDensityMatrix)
+
1131  densmatr_applyDiagonalOp(qureg, op);
+
1132  else
+
1133  statevec_applyDiagonalOp(qureg, op);
+
1134 
+
1135  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
+
1136 }
+
1137 
+
1138 
+
1139 /*
+
1140  * calculations
+
1141  */
+
1142 
+ +
1144  if (qureg.isDensityMatrix)
+
1145  return densmatr_calcTotalProb(qureg);
+
1146  else
+
1147  return statevec_calcTotalProb(qureg);
+
1148 }
+
1149 
+ +
1151  validateStateVecQureg(bra, __func__);
+
1152  validateStateVecQureg(ket, __func__);
+
1153  validateMatchingQuregDims(bra, ket, __func__);
+
1154 
+
1155  return statevec_calcInnerProduct(bra, ket);
+
1156 }
+
1157 
+ +
1159  validateDensityMatrQureg(rho1, __func__);
+
1160  validateDensityMatrQureg(rho2, __func__);
+
1161  validateMatchingQuregDims(rho1, rho2, __func__);
+
1162 
+
1163  return densmatr_calcInnerProduct(rho1, rho2);
+
1164 }
1165 
-
1166  if (qureg.isDensityMatrix)
-
1167  densmatr_calcProbOfAllOutcomes(retProbs, qureg, qubits, numQubits);
-
1168  else
-
1169  statevec_calcProbOfAllOutcomes(retProbs, qureg, qubits, numQubits);
-
1170 }
-
1171 
- -
1173  validateDensityMatrQureg(qureg, __func__);
-
1174 
-
1175  return densmatr_calcPurity(qureg);
-
1176 }
-
1177 
-
1178 qreal calcFidelity(Qureg qureg, Qureg pureState) {
-
1179  validateSecondQuregStateVec(pureState, __func__);
-
1180  validateMatchingQuregDims(qureg, pureState, __func__);
-
1181 
-
1182  if (qureg.isDensityMatrix)
-
1183  return densmatr_calcFidelity(qureg, pureState);
-
1184  else
-
1185  return statevec_calcFidelity(qureg, pureState);
-
1186 }
-
1187 
-
1188 qreal calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace) {
-
1189  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
-
1190  validatePauliCodes(pauliCodes, numTargets, __func__);
-
1191  validateMatchingQuregTypes(qureg, workspace, __func__);
-
1192  validateMatchingQuregDims(qureg, workspace, __func__);
-
1193 
-
1194  return statevec_calcExpecPauliProd(qureg, targetQubits, pauliCodes, numTargets, workspace);
-
1195 }
-
1196 
-
1197 qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace) {
-
1198  validateNumPauliSumTerms(numSumTerms, __func__);
-
1199  validatePauliCodes(allPauliCodes, numSumTerms*qureg.numQubitsRepresented, __func__);
-
1200  validateMatchingQuregTypes(qureg, workspace, __func__);
-
1201  validateMatchingQuregDims(qureg, workspace, __func__);
-
1202 
-
1203  return statevec_calcExpecPauliSum(qureg, allPauliCodes, termCoeffs, numSumTerms, workspace);
-
1204 }
-
1205 
-
1206 qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace) {
-
1207  validateMatchingQuregTypes(qureg, workspace, __func__);
-
1208  validateMatchingQuregDims(qureg, workspace, __func__);
-
1209  validatePauliHamil(hamil, __func__);
-
1210  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
-
1211 
-
1212  return statevec_calcExpecPauliSum(qureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, workspace);
-
1213 }
-
1214 
- -
1216  validateDiagonalOp(qureg, op, __func__);
-
1217 
-
1218  if (qureg.isDensityMatrix)
-
1219  return densmatr_calcExpecDiagonalOp(qureg, op);
-
1220  else
-
1221  return statevec_calcExpecDiagonalOp(qureg, op);
-
1222 }
-
1223 
- -
1225  validateDensityMatrQureg(a, __func__);
-
1226  validateDensityMatrQureg(b, __func__);
-
1227  validateMatchingQuregDims(a, b, __func__);
-
1228 
- -
1230 }
-
1231 
-
1232 
-
1233 /*
-
1234  * decoherence
-
1235  */
+
1166 qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
+
1167  validateTarget(qureg, measureQubit, __func__);
+
1168  validateOutcome(outcome, __func__);
+
1169 
+
1170  if (qureg.isDensityMatrix)
+
1171  return densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
+
1172  else
+
1173  return statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
+
1174 }
+
1175 
+
1176 void calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
+
1177  validateMultiTargets(qureg, qubits, numQubits, __func__);
+
1178 
+
1179  if (qureg.isDensityMatrix)
+
1180  densmatr_calcProbOfAllOutcomes(retProbs, qureg, qubits, numQubits);
+
1181  else
+
1182  statevec_calcProbOfAllOutcomes(retProbs, qureg, qubits, numQubits);
+
1183 }
+
1184 
+ +
1186  validateDensityMatrQureg(qureg, __func__);
+
1187 
+
1188  return densmatr_calcPurity(qureg);
+
1189 }
+
1190 
+
1191 qreal calcFidelity(Qureg qureg, Qureg pureState) {
+
1192  validateSecondQuregStateVec(pureState, __func__);
+
1193  validateMatchingQuregDims(qureg, pureState, __func__);
+
1194 
+
1195  if (qureg.isDensityMatrix)
+
1196  return densmatr_calcFidelity(qureg, pureState);
+
1197  else
+
1198  return statevec_calcFidelity(qureg, pureState);
+
1199 }
+
1200 
+
1201 qreal calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace) {
+
1202  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
+
1203  validatePauliCodes(pauliCodes, numTargets, __func__);
+
1204  validateMatchingQuregTypes(qureg, workspace, __func__);
+
1205  validateMatchingQuregDims(qureg, workspace, __func__);
+
1206 
+
1207  return statevec_calcExpecPauliProd(qureg, targetQubits, pauliCodes, numTargets, workspace);
+
1208 }
+
1209 
+
1210 qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace) {
+
1211  validateNumPauliSumTerms(numSumTerms, __func__);
+
1212  validatePauliCodes(allPauliCodes, numSumTerms*qureg.numQubitsRepresented, __func__);
+
1213  validateMatchingQuregTypes(qureg, workspace, __func__);
+
1214  validateMatchingQuregDims(qureg, workspace, __func__);
+
1215 
+
1216  return statevec_calcExpecPauliSum(qureg, allPauliCodes, termCoeffs, numSumTerms, workspace);
+
1217 }
+
1218 
+
1219 qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace) {
+
1220  validateMatchingQuregTypes(qureg, workspace, __func__);
+
1221  validateMatchingQuregDims(qureg, workspace, __func__);
+
1222  validatePauliHamil(hamil, __func__);
+
1223  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
+
1224 
+
1225  return statevec_calcExpecPauliSum(qureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, workspace);
+
1226 }
+
1227 
+ +
1229  validateDiagonalOp(qureg, op, __func__);
+
1230 
+
1231  if (qureg.isDensityMatrix)
+
1232  return densmatr_calcExpecDiagonalOp(qureg, op);
+
1233  else
+
1234  return statevec_calcExpecDiagonalOp(qureg, op);
+
1235 }
1236 
-
1237 void mixDephasing(Qureg qureg, int targetQubit, qreal prob) {
-
1238  validateDensityMatrQureg(qureg, __func__);
-
1239  validateTarget(qureg, targetQubit, __func__);
-
1240  validateOneQubitDephaseProb(prob, __func__);
+ +
1238  validateDensityMatrQureg(a, __func__);
+
1239  validateDensityMatrQureg(b, __func__);
+
1240  validateMatchingQuregDims(a, b, __func__);
1241 
-
1242  densmatr_mixDephasing(qureg, targetQubit, 2*prob);
-
1243  qasm_recordComment(qureg,
-
1244  "Here, a phase (Z) error occured on qubit %d with probability %g", targetQubit, prob);
-
1245 }
-
1246 
-
1247 void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob) {
-
1248  validateDensityMatrQureg(qureg, __func__);
-
1249  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
-
1250  validateTwoQubitDephaseProb(prob, __func__);
-
1251 
-
1252  ensureIndsIncrease(&qubit1, &qubit2);
-
1253  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, (4*prob)/3.0);
-
1254  qasm_recordComment(qureg,
-
1255  "Here, a phase (Z) error occured on either or both of qubits "
-
1256  "%d and %d with total probability %g", qubit1, qubit2, prob);
-
1257 }
-
1258 
-
1259 void mixDepolarising(Qureg qureg, int targetQubit, qreal prob) {
-
1260  validateDensityMatrQureg(qureg, __func__);
-
1261  validateTarget(qureg, targetQubit, __func__);
-
1262  validateOneQubitDepolProb(prob, __func__);
-
1263 
-
1264  densmatr_mixDepolarising(qureg, targetQubit, (4*prob)/3.0);
-
1265  qasm_recordComment(qureg,
-
1266  "Here, a homogeneous depolarising error (X, Y, or Z) occured on "
-
1267  "qubit %d with total probability %g", targetQubit, prob);
-
1268 }
-
1269 
-
1270 void mixDamping(Qureg qureg, int targetQubit, qreal prob) {
-
1271  validateDensityMatrQureg(qureg, __func__);
-
1272  validateTarget(qureg, targetQubit, __func__);
-
1273  validateOneQubitDampingProb(prob, __func__);
-
1274 
-
1275  densmatr_mixDamping(qureg, targetQubit, prob);
-
1276 }
-
1277 
-
1278 void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob) {
-
1279  validateDensityMatrQureg(qureg, __func__);
-
1280  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
-
1281  validateTwoQubitDepolProb(prob, __func__);
-
1282 
-
1283  ensureIndsIncrease(&qubit1, &qubit2);
-
1284  densmatr_mixTwoQubitDepolarising(qureg, qubit1, qubit2, (16*prob)/15.0);
-
1285  qasm_recordComment(qureg,
-
1286  "Here, a homogeneous depolarising error occured on qubits %d and %d "
-
1287  "with total probability %g", qubit1, qubit2, prob);
-
1288 }
-
1289 
-
1290 void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ) {
-
1291  validateDensityMatrQureg(qureg, __func__);
-
1292  validateTarget(qureg, qubit, __func__);
-
1293  validateOneQubitPauliProbs(probX, probY, probZ, __func__);
-
1294 
-
1295  densmatr_mixPauli(qureg, qubit, probX, probY, probZ);
-
1296  qasm_recordComment(qureg,
-
1297  "Here, X, Y and Z errors occured on qubit %d with probabilities "
-
1298  "%g, %g and %g respectively", qubit, probX, probY, probZ);
-
1299 }
-
1300 
-
1301 void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps) {
-
1302  validateDensityMatrQureg(qureg, __func__);
-
1303  validateTarget(qureg, target, __func__);
-
1304  validateOneQubitKrausMap(qureg, ops, numOps, __func__);
-
1305 
-
1306  densmatr_mixKrausMap(qureg, target, ops, numOps);
-
1307  qasm_recordComment(qureg,
-
1308  "Here, an undisclosed Kraus map was effected on qubit %d", target);
-
1309 }
-
1310 
-
1311 void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps) {
-
1312  validateDensityMatrQureg(qureg, __func__);
-
1313  validateMultiTargets(qureg, (int[]) {target1,target2}, 2, __func__);
-
1314  validateTwoQubitKrausMap(qureg, ops, numOps, __func__);
-
1315 
-
1316  densmatr_mixTwoQubitKrausMap(qureg, target1, target2, ops, numOps);
-
1317  qasm_recordComment(qureg,
-
1318  "Here, an undisclosed two-qubit Kraus map was effected on qubits %d and %d", target1, target2);
-
1319 }
-
1320 
-
1321 void mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps) {
-
1322  validateDensityMatrQureg(qureg, __func__);
-
1323  validateMultiTargets(qureg, targets, numTargets, __func__);
-
1324  validateMultiQubitKrausMap(qureg, numTargets, ops, numOps, __func__);
-
1325 
-
1326  densmatr_mixMultiQubitKrausMap(qureg, targets, numTargets, ops, numOps);
-
1327  qasm_recordComment(qureg,
-
1328  "Here, an undisclosed %d-qubit Kraus map was applied to undisclosed qubits", numTargets);
-
1329 }
-
1330 
-
1331 /*
-
1332  * other data structures
-
1333  */
-
1334 
- -
1336  validateNumQubitsInMatrix(numQubits, __func__);
-
1337 
-
1338  int numRows = 1 << numQubits;
-
1339 
-
1340  ComplexMatrixN m = {
-
1341  .numQubits = numQubits,
-
1342  .real = malloc(numRows * sizeof *m.real),
-
1343  .imag = malloc(numRows * sizeof *m.imag)};
-
1344 
-
1345  for (int n=0; n < 1<<numQubits; n++) {
-
1346  m.real[n] = calloc(numRows, sizeof **m.real);
-
1347  m.imag[n] = calloc(numRows, sizeof **m.imag);
-
1348  }
-
1349 
-
1350  // error if the ComplexMatrixN was not successfully malloc'ds
-
1351  validateMatrixInit(m, __func__);
-
1352 
-
1353  return m;
-
1354  }
-
1355 
- -
1357  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
-
1358  * in createComplexMatrixN fail, which already prompts an error. Hence
-
1359  * this check if useless
-
1360  */
-
1361  validateMatrixInit(m, __func__);
-
1362 
-
1363  int numRows = 1 << m.numQubits;
-
1364  for (int r=0; r < numRows; r++) {
-
1365  free(m.real[r]);
-
1366  free(m.imag[r]);
-
1367  }
-
1368  free(m.real);
-
1369  free(m.imag);
-
1370 }
-
1371 
- -
1373  validateMatrixInit(m, __func__);
-
1374 
-
1375  int dim = 1 << m.numQubits;
-
1376  for (int i=0; i<dim; i++)
-
1377  for (int j=0; j<dim; j++) {
-
1378  m.real[i][j] = re[i][j];
-
1379  m.imag[i][j] = im[i][j];
-
1380  }
-
1381 }
-
1382 
-
1383 PauliHamil createPauliHamil(int numQubits, int numSumTerms) {
-
1384  validateHamilParams(numQubits, numSumTerms, __func__);
-
1385 
-
1386  PauliHamil h;
-
1387  h.numQubits = numQubits;
-
1388  h.numSumTerms = numSumTerms;
-
1389  h.termCoeffs = malloc(numSumTerms * sizeof *h.termCoeffs);
-
1390  h.pauliCodes = malloc(numQubits*numSumTerms * sizeof *h.pauliCodes);
-
1391 
-
1392  // initialise pauli codes to identity
-
1393  for (int i=0; i<numQubits*numSumTerms; i++)
-
1394  h.pauliCodes[i] = PAULI_I;
-
1395 
-
1396  return h;
-
1397 }
-
1398 
- + +
1243 }
+
1244 
+
1245 
+
1246 /*
+
1247  * decoherence
+
1248  */
+
1249 
+
1250 void mixDephasing(Qureg qureg, int targetQubit, qreal prob) {
+
1251  validateDensityMatrQureg(qureg, __func__);
+
1252  validateTarget(qureg, targetQubit, __func__);
+
1253  validateOneQubitDephaseProb(prob, __func__);
+
1254 
+
1255  densmatr_mixDephasing(qureg, targetQubit, 2*prob);
+
1256  qasm_recordComment(qureg,
+
1257  "Here, a phase (Z) error occured on qubit %d with probability %g", targetQubit, prob);
+
1258 }
+
1259 
+
1260 void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob) {
+
1261  validateDensityMatrQureg(qureg, __func__);
+
1262  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
+
1263  validateTwoQubitDephaseProb(prob, __func__);
+
1264 
+
1265  ensureIndsIncrease(&qubit1, &qubit2);
+
1266  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, (4*prob)/3.0);
+
1267  qasm_recordComment(qureg,
+
1268  "Here, a phase (Z) error occured on either or both of qubits "
+
1269  "%d and %d with total probability %g", qubit1, qubit2, prob);
+
1270 }
+
1271 
+
1272 void mixDepolarising(Qureg qureg, int targetQubit, qreal prob) {
+
1273  validateDensityMatrQureg(qureg, __func__);
+
1274  validateTarget(qureg, targetQubit, __func__);
+
1275  validateOneQubitDepolProb(prob, __func__);
+
1276 
+
1277  densmatr_mixDepolarising(qureg, targetQubit, (4*prob)/3.0);
+
1278  qasm_recordComment(qureg,
+
1279  "Here, a homogeneous depolarising error (X, Y, or Z) occured on "
+
1280  "qubit %d with total probability %g", targetQubit, prob);
+
1281 }
+
1282 
+
1283 void mixDamping(Qureg qureg, int targetQubit, qreal prob) {
+
1284  validateDensityMatrQureg(qureg, __func__);
+
1285  validateTarget(qureg, targetQubit, __func__);
+
1286  validateOneQubitDampingProb(prob, __func__);
+
1287 
+
1288  densmatr_mixDamping(qureg, targetQubit, prob);
+
1289 }
+
1290 
+
1291 void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob) {
+
1292  validateDensityMatrQureg(qureg, __func__);
+
1293  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
+
1294  validateTwoQubitDepolProb(prob, __func__);
+
1295 
+
1296  ensureIndsIncrease(&qubit1, &qubit2);
+
1297  densmatr_mixTwoQubitDepolarising(qureg, qubit1, qubit2, (16*prob)/15.0);
+
1298  qasm_recordComment(qureg,
+
1299  "Here, a homogeneous depolarising error occured on qubits %d and %d "
+
1300  "with total probability %g", qubit1, qubit2, prob);
+
1301 }
+
1302 
+
1303 void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ) {
+
1304  validateDensityMatrQureg(qureg, __func__);
+
1305  validateTarget(qureg, qubit, __func__);
+
1306  validateOneQubitPauliProbs(probX, probY, probZ, __func__);
+
1307 
+
1308  densmatr_mixPauli(qureg, qubit, probX, probY, probZ);
+
1309  qasm_recordComment(qureg,
+
1310  "Here, X, Y and Z errors occured on qubit %d with probabilities "
+
1311  "%g, %g and %g respectively", qubit, probX, probY, probZ);
+
1312 }
+
1313 
+
1314 void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps) {
+
1315  validateDensityMatrQureg(qureg, __func__);
+
1316  validateTarget(qureg, target, __func__);
+
1317  validateOneQubitKrausMap(qureg, ops, numOps, __func__);
+
1318 
+
1319  densmatr_mixKrausMap(qureg, target, ops, numOps);
+
1320  qasm_recordComment(qureg,
+
1321  "Here, an undisclosed Kraus map was effected on qubit %d", target);
+
1322 }
+
1323 
+
1324 void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps) {
+
1325  validateDensityMatrQureg(qureg, __func__);
+
1326  validateMultiTargets(qureg, (int[]) {target1,target2}, 2, __func__);
+
1327  validateTwoQubitKrausMap(qureg, ops, numOps, __func__);
+
1328 
+
1329  densmatr_mixTwoQubitKrausMap(qureg, target1, target2, ops, numOps);
+
1330  qasm_recordComment(qureg,
+
1331  "Here, an undisclosed two-qubit Kraus map was effected on qubits %d and %d", target1, target2);
+
1332 }
+
1333 
+
1334 void mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps) {
+
1335  validateDensityMatrQureg(qureg, __func__);
+
1336  validateMultiTargets(qureg, targets, numTargets, __func__);
+
1337  validateMultiQubitKrausMap(qureg, numTargets, ops, numOps, __func__);
+
1338 
+
1339  densmatr_mixMultiQubitKrausMap(qureg, targets, numTargets, ops, numOps);
+
1340  qasm_recordComment(qureg,
+
1341  "Here, an undisclosed %d-qubit Kraus map was applied to undisclosed qubits", numTargets);
+
1342 }
+
1343 
+
1344 /*
+
1345  * other data structures
+
1346  */
+
1347 
+ +
1349  validateNumQubitsInMatrix(numQubits, __func__);
+
1350 
+
1351  int numRows = 1 << numQubits;
+
1352 
+
1353  ComplexMatrixN m = {
+
1354  .numQubits = numQubits,
+
1355  .real = malloc(numRows * sizeof *m.real),
+
1356  .imag = malloc(numRows * sizeof *m.imag)};
+
1357 
+
1358  for (int n=0; n < 1<<numQubits; n++) {
+
1359  m.real[n] = calloc(numRows, sizeof **m.real);
+
1360  m.imag[n] = calloc(numRows, sizeof **m.imag);
+
1361  }
+
1362 
+
1363  // error if the ComplexMatrixN was not successfully malloc'ds
+
1364  validateMatrixInit(m, __func__);
+
1365 
+
1366  return m;
+
1367  }
+
1368 
+ +
1370  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
+
1371  * in createComplexMatrixN fail, which already prompts an error. Hence
+
1372  * this check if useless
+
1373  */
+
1374  validateMatrixInit(m, __func__);
+
1375 
+
1376  int numRows = 1 << m.numQubits;
+
1377  for (int r=0; r < numRows; r++) {
+
1378  free(m.real[r]);
+
1379  free(m.imag[r]);
+
1380  }
+
1381  free(m.real);
+
1382  free(m.imag);
+
1383 }
+
1384 
+
1385 #ifndef _WIN32
+ +
1387  validateMatrixInit(m, __func__);
+
1388 
+
1389  int dim = 1 << m.numQubits;
+
1390  for (int i=0; i<dim; i++)
+
1391  for (int j=0; j<dim; j++) {
+
1392  m.real[i][j] = re[i][j];
+
1393  m.imag[i][j] = im[i][j];
+
1394  }
+
1395 }
+
1396 #endif
+
1397 
+
1398 PauliHamil createPauliHamil(int numQubits, int numSumTerms) {
+
1399  validateHamilParams(numQubits, numSumTerms, __func__);
1400 
-
1401  free(h.termCoeffs);
-
1402  free(h.pauliCodes);
-
1403 }
-
1404 
- +
1401  PauliHamil h;
+
1402  h.numQubits = numQubits;
+
1403  h.numSumTerms = numSumTerms;
+
1404  h.termCoeffs = malloc(numSumTerms * sizeof *h.termCoeffs);
+
1405  h.pauliCodes = malloc(numQubits*numSumTerms * sizeof *h.pauliCodes);
1406 
-
1407  /* The validation in this function must close the file handle and free
-
1408  * allocated memory before raising an error (whether that's a C exit, or
-
1409  * an overriden C++ exception).
-
1410  */
-
1411 
-
1412  FILE* file = fopen(fn, "r");
-
1413  int success = (file != NULL);
-
1414  validateFileOpened(success, fn, __func__);
+
1407  // initialise pauli codes to identity
+
1408  for (int i=0; i<numQubits*numSumTerms; i++)
+
1409  h.pauliCodes[i] = PAULI_I;
+
1410 
+
1411  return h;
+
1412 }
+
1413 
+
1415 
-
1416  /* file format: coeff {term} \n where {term} is #numQubits values of
-
1417  * 0 1 2 3 signifying I X Y Z acting on that qubit index
-
1418  */
-
1419 
-
1420  // count the number of qubits (ignore trailing whitespace)
-
1421  int numQubits = -1; // to exclude coeff at start
-
1422  char ch = getc(file);
-
1423  char prev = '0'; // anything not space
-
1424  while (ch != '\n' && ch != EOF) {
-
1425  if (ch == ' ' && prev != ' ') // skip multiple spaces
-
1426  numQubits++;
-
1427  prev = ch;
-
1428  ch = getc(file);
-
1429  }
-
1430  // edge-case: if we hit EOF/newline without a space
-
1431  if (prev != ' ')
-
1432  numQubits++;
-
1433 
-
1434  /* TODO:
-
1435  * The below code may break on Windows where newlines are multiple characters
-
1436  */
-
1437 
-
1438  // count the number of terms (being cautious of trailing newlines)
-
1439  int numTerms = 0;
-
1440  prev = '\n';
-
1441  rewind(file);
-
1442  while ((ch=getc(file)) != EOF) {
-
1443  if (ch == '\n' && prev != '\n')
-
1444  numTerms++;
-
1445  prev = ch;
-
1446  }
-
1447  // edge-case: if we hit EOF without a newline, count that line
-
1448  if (prev != '\n')
-
1449  numTerms++;
-
1450 
-
1451  // validate the inferred number of terms and qubits (closes file if error)
-
1452  validateHamilFileParams(numQubits, numTerms, file, fn, __func__);
-
1453 
-
1454  // allocate space for PauliHamil data
-
1455  PauliHamil h = createPauliHamil(numQubits, numTerms);
-
1456 
-
1457  // specifier for a qreal number then a space
-
1458  char strSpec[50];
-
1459  strcpy(strSpec, REAL_SPECIFIER);
-
1460  strcat(strSpec, " ");
-
1461 
-
1462  // collect coefficients and terms
-
1463  rewind(file);
-
1464  for (int t=0; t<numTerms; t++) {
-
1465 
-
1466  // record coefficient, and validate (closes file and frees h if error)
-
1467  success = fscanf(file, strSpec, &(h.termCoeffs[t])) == 1;
-
1468  validateHamilFileCoeffParsed(success, h, file, fn, __func__);
-
1469 
-
1470  // record Pauli operations, and validate (closes file and frees h if error)
-
1471  for (int q=0; q<numQubits; q++) {
-
1472  int i = t*numQubits + q;
-
1473 
-
1474  // verbose, to avoid type warnings
-
1475  int code;
-
1476  success = fscanf(file, "%d ", &code) == 1;
-
1477  h.pauliCodes[i] = (enum pauliOpType) code;
-
1478  validateHamilFilePauliParsed(success, h, file, fn, __func__);
-
1479  validateHamilFilePauliCode(h.pauliCodes[i], h, file, fn, __func__);
-
1480  }
-
1481 
-
1482  // the trailing newline is magically eaten
-
1483  }
+
1416  free(h.termCoeffs);
+
1417  free(h.pauliCodes);
+
1418 }
+
1419 
+ +
1421 
+
1422  /* The validation in this function must close the file handle and free
+
1423  * allocated memory before raising an error (whether that's a C exit, or
+
1424  * an overriden C++ exception).
+
1425  */
+
1426 
+
1427  FILE* file = fopen(fn, "r");
+
1428  int success = (file != NULL);
+
1429  validateFileOpened(success, fn, __func__);
+
1430 
+
1431  /* file format: coeff {term} \n where {term} is #numQubits values of
+
1432  * 0 1 2 3 signifying I X Y Z acting on that qubit index
+
1433  */
+
1434 
+
1435  // count the number of qubits (ignore trailing whitespace)
+
1436  int numQubits = -1; // to exclude coeff at start
+
1437  char ch = getc(file);
+
1438  char prev = '0'; // anything not space
+
1439  while (ch != '\n' && ch != EOF) {
+
1440  if (ch == ' ' && prev != ' ') // skip multiple spaces
+
1441  numQubits++;
+
1442  prev = ch;
+
1443  ch = getc(file);
+
1444  }
+
1445  // edge-case: if we hit EOF/newline without a space
+
1446  if (prev != ' ')
+
1447  numQubits++;
+
1448 
+
1449  /* TODO:
+
1450  * The below code may break on Windows where newlines are multiple characters
+
1451  */
+
1452 
+
1453  // count the number of terms (being cautious of trailing newlines)
+
1454  int numTerms = 0;
+
1455  prev = '\n';
+
1456  rewind(file);
+
1457  while ((ch=getc(file)) != EOF) {
+
1458  if (ch == '\n' && prev != '\n')
+
1459  numTerms++;
+
1460  prev = ch;
+
1461  }
+
1462  // edge-case: if we hit EOF without a newline, count that line
+
1463  if (prev != '\n')
+
1464  numTerms++;
+
1465 
+
1466  // validate the inferred number of terms and qubits (closes file if error)
+
1467  validateHamilFileParams(numQubits, numTerms, file, fn, __func__);
+
1468 
+
1469  // allocate space for PauliHamil data
+
1470  PauliHamil h = createPauliHamil(numQubits, numTerms);
+
1471 
+
1472  // specifier for a qreal number then a space
+
1473  char strSpec[50];
+
1474  strcpy(strSpec, REAL_SPECIFIER);
+
1475  strcat(strSpec, " ");
+
1476 
+
1477  // collect coefficients and terms
+
1478  rewind(file);
+
1479  for (int t=0; t<numTerms; t++) {
+
1480 
+
1481  // record coefficient, and validate (closes file and frees h if error)
+
1482  success = fscanf(file, strSpec, &(h.termCoeffs[t])) == 1;
+
1483  validateHamilFileCoeffParsed(success, h, file, fn, __func__);
1484 
-
1485  fclose(file);
-
1486  return h;
-
1487 }
-
1488 
-
1489 void initPauliHamil(PauliHamil hamil, qreal* coeffs, enum pauliOpType* codes) {
-
1490  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
-
1491  validatePauliCodes(codes, hamil.numSumTerms*hamil.numQubits, __func__);
-
1492 
-
1493  int i=0;
-
1494  for (int t=0; t<hamil.numSumTerms; t++) {
-
1495  hamil.termCoeffs[t] = coeffs[t];
-
1496  for (int q=0; q<hamil.numQubits; q++) {
-
1497  hamil.pauliCodes[i] = codes[i];
-
1498  i++;
-
1499  }
-
1500  }
-
1501 }
-
1502 
-
1503 DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env) {
-
1504  validateNumQubitsInDiagOp(numQubits, env.numRanks, __func__);
-
1505 
-
1506  return agnostic_createDiagonalOp(numQubits, env);
-
1507 }
-
1508 
- -
1510  // env accepted for API consistency
-
1511  validateDiagOpInit(op, __func__);
-
1512 
- -
1514 }
-
1515 
- -
1517  validateDiagOpInit(op, __func__);
-
1518 
- -
1520 }
-
1521 
-
1522 void initDiagonalOp(DiagonalOp op, qreal* real, qreal* imag) {
-
1523  validateDiagOpInit(op, __func__);
-
1524 
-
1525  agnostic_setDiagonalOpElems(op, 0, real, imag, 1LL << op.numQubits);
-
1526 }
-
1527 
-
1528 void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
-
1529  validateDiagOpInit(op, __func__);
-
1530  validateNumElems(op, startInd, numElems, __func__);
-
1531 
-
1532  agnostic_setDiagonalOpElems(op, startInd, real, imag, numElems);
-
1533 }
-
1534 
- -
1536  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
-
1537  validateDiagOpInit(op, __func__);
-
1538  validateDiagPauliHamil(op, hamil, __func__);
+
1485  // record Pauli operations, and validate (closes file and frees h if error)
+
1486  for (int q=0; q<numQubits; q++) {
+
1487  int i = t*numQubits + q;
+
1488 
+
1489  // verbose, to avoid type warnings
+
1490  int code;
+
1491  success = fscanf(file, "%d ", &code) == 1;
+
1492  h.pauliCodes[i] = (enum pauliOpType) code;
+
1493  validateHamilFilePauliParsed(success, h, file, fn, __func__);
+
1494  validateHamilFilePauliCode(h.pauliCodes[i], h, file, fn, __func__);
+
1495  }
+
1496 
+
1497  // the trailing newline is magically eaten
+
1498  }
+
1499 
+
1500  fclose(file);
+
1501  return h;
+
1502 }
+
1503 
+
1504 void initPauliHamil(PauliHamil hamil, qreal* coeffs, enum pauliOpType* codes) {
+
1505  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
+
1506  validatePauliCodes(codes, hamil.numSumTerms*hamil.numQubits, __func__);
+
1507 
+
1508  int i=0;
+
1509  for (int t=0; t<hamil.numSumTerms; t++) {
+
1510  hamil.termCoeffs[t] = coeffs[t];
+
1511  for (int q=0; q<hamil.numQubits; q++) {
+
1512  hamil.pauliCodes[i] = codes[i];
+
1513  i++;
+
1514  }
+
1515  }
+
1516 }
+
1517 
+
1518 DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env) {
+
1519  validateNumQubitsInDiagOp(numQubits, env.numRanks, __func__);
+
1520 
+
1521  return agnostic_createDiagonalOp(numQubits, env);
+
1522 }
+
1523 
+ +
1525  // env accepted for API consistency
+
1526  validateDiagOpInit(op, __func__);
+
1527 
+ +
1529 }
+
1530 
+ +
1532  validateDiagOpInit(op, __func__);
+
1533 
+ +
1535 }
+
1536 
+
1537 void initDiagonalOp(DiagonalOp op, qreal* real, qreal* imag) {
+
1538  validateDiagOpInit(op, __func__);
1539 
- +
1540  agnostic_setDiagonalOpElems(op, 0, real, imag, 1LL << op.numQubits);
1541 }
1542 
- -
1544  PauliHamil h = createPauliHamilFromFile(fn); // validates fn
-
1545  validateDiagPauliHamilFromFile(h, env.numRanks, __func__); // destroys h if invalid
-
1546 
- - -
1549 
-
1550  destroyPauliHamil(h);
-
1551  return op;
-
1552 }
-
1553 
-
1554 /*
-
1555  * debug
-
1556  */
+
1543 void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
+
1544  validateDiagOpInit(op, __func__);
+
1545  validateNumElems(op, startInd, numElems, __func__);
+
1546 
+
1547  agnostic_setDiagonalOpElems(op, startInd, real, imag, numElems);
+
1548 }
+
1549 
+ +
1551  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
+
1552  validateDiagOpInit(op, __func__);
+
1553  validateDiagPauliHamil(op, hamil, __func__);
+
1554 
+ +
1556 }
1557 
-
1558 int compareStates(Qureg qureg1, Qureg qureg2, qreal precision) {
-
1559  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1560  return statevec_compareStates(qureg1, qureg2, precision);
-
1561 }
-
1562 
-
1563 void initDebugState(Qureg qureg) {
-
1564  statevec_initDebugState(qureg);
-
1565 }
-
1566 
-
1567 void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env) {
-
1568  int success = statevec_initStateFromSingleFile(qureg, filename, env);
-
1569  validateFileOpened(success, filename, __func__);
-
1570 }
-
1571 
-
1572 void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome) {
-
1573  validateStateVecQureg(*qureg, __func__);
-
1574  validateTarget(*qureg, qubitId, __func__);
-
1575  validateOutcome(outcome, __func__);
-
1576  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
-
1577 }
-
1578 
-
1579 void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank) {
-
1580  statevec_reportStateToScreen(qureg, env, reportRank);
-
1581 }
-
1582 
- -
1584  validatePauliHamil(hamil, __func__);
-
1585 
-
1586  for (int t=0; t<hamil.numSumTerms; t++) {
-
1587  printf(REAL_QASM_FORMAT, hamil.termCoeffs[t]);
-
1588  printf("\t");
-
1589  for (int q=0; q<hamil.numQubits; q++)
-
1590  printf("%d ", (int) hamil.pauliCodes[q+t*hamil.numQubits]);
-
1591  printf("\n");
-
1592  }
-
1593 }
-
1594 
-
1595 int getQuEST_PREC(void) {
-
1596  return sizeof(qreal)/4;
-
1597 }
-
1598 
-
1599 
-
1600 #ifdef __cplusplus
-
1601 }
-
1602 #endif
+ +
1559  PauliHamil h = createPauliHamilFromFile(fn); // validates fn
+
1560  validateDiagPauliHamilFromFile(h, env.numRanks, __func__); // destroys h if invalid
+
1561 
+ + +
1564 
+
1565  destroyPauliHamil(h);
+
1566  return op;
+
1567 }
+
1568 
+
1569 /*
+
1570  * debug
+
1571  */
+
1572 
+
1573 int compareStates(Qureg qureg1, Qureg qureg2, qreal precision) {
+
1574  validateMatchingQuregDims(qureg1, qureg2, __func__);
+
1575  return statevec_compareStates(qureg1, qureg2, precision);
+
1576 }
+
1577 
+
1578 void initDebugState(Qureg qureg) {
+
1579  statevec_initDebugState(qureg);
+
1580 }
+
1581 
+
1582 void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env) {
+
1583  int success = statevec_initStateFromSingleFile(qureg, filename, env);
+
1584  validateFileOpened(success, filename, __func__);
+
1585 }
+
1586 
+
1587 void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome) {
+
1588  validateStateVecQureg(*qureg, __func__);
+
1589  validateTarget(*qureg, qubitId, __func__);
+
1590  validateOutcome(outcome, __func__);
+
1591  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
+
1592 }
+
1593 
+
1594 void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank) {
+
1595  statevec_reportStateToScreen(qureg, env, reportRank);
+
1596 }
+
1597 
+ +
1599  validatePauliHamil(hamil, __func__);
+
1600 
+
1601  for (int t=0; t<hamil.numSumTerms; t++) {
+
1602  printf(REAL_QASM_FORMAT, hamil.termCoeffs[t]);
+
1603  printf("\t");
+
1604  for (int q=0; q<hamil.numQubits; q++)
+
1605  printf("%d ", (int) hamil.pauliCodes[q+t*hamil.numQubits]);
+
1606  printf("\n");
+
1607  }
+
1608 }
+
1609 
+
1610 int getQuEST_PREC(void) {
+
1611  return sizeof(qreal)/4;
+
1612 }
+
1613 
+ +
1615 
+
1616  // seed Mersenne Twister random number generator with two keys -- time and pid
+
1617  unsigned long int keys[2];
+
1618  getQuESTDefaultSeedKey(keys);
+
1619  seedQuEST(env, keys, 2);
+
1620 }
+
1621 
+
1622 void getQuESTSeeds(QuESTEnv env, unsigned long int** seeds, int* numSeeds) {
+
1623  *seeds = env.seeds;
+
1624  *numSeeds = env.numSeeds;
+
1625 }
+
1626 
+
1627 
+
1628 #ifdef __cplusplus
+
1629 }
+
1630 #endif
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1357
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:245
+
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1368
+
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
+
void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:244
void qasm_printRecorded(Qureg qureg)
Definition: QuEST_qasm.c:871
-
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:264
-
void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:1237
-
int compareStates(Qureg qureg1, Qureg qureg2, qreal precision)
Return whether two given wavefunctions are equivalent within a given precision Global phase included ...
Definition: QuEST.c:1558
-
qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:919
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
+
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:254
+
void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:1250
+
int compareStates(Qureg qureg1, Qureg qureg2, qreal precision)
Return whether two given wavefunctions are equivalent within a given precision Global phase included ...
Definition: QuEST.c:1573
+
qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:932
+
void validateDensityMatrQureg(Qureg qureg, const char *caller)
void initBlankState(Qureg qureg)
Initialises a qureg to have all-zero-amplitudes.
Definition: QuEST.c:119
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
-
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
-
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:278
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:271
+
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
+
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:268
+
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:261
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:306
-
void validateMeasurementProb(qreal prob, const char *caller)
-
void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:727
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
Definition: QuEST.c:1101
-
void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:257
-
void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:221
-
void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:814
-
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:836
-
void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
Definition: QuEST.c:1489
-
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
-
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:654
+
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:296
+
void validateMeasurementProb(qreal prob, const char *caller)
+
void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:726
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
Definition: QuEST.c:1114
+
void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:256
+
void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:220
+
void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:813
+
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:849
+
void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
Definition: QuEST.c:1504
+
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
+
void validateOutcome(int outcome, const char *caller)
+
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
+
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
+
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:644
void initPureState(Qureg qureg, Qureg pure)
Initialise qureg into to a given pure state of an equivalent Hilbert dimension.
Definition: QuEST.c:145
-
void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:602
-
void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:1259
-
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
Definition: QuEST_common.c:463
+
void applyProjector(Qureg qureg, int qubit, int outcome)
Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection.
Definition: QuEST.c:888
+
void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:601
+
void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:1272
+
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
Definition: QuEST_common.c:453
void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param)
Definition: QuEST_qasm.c:187
-
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
-
void densmatr_initPlusState(Qureg targetQureg)
Definition: QuEST_cpu.c:1154
-
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:1130
-
void mixDamping(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:1270
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1356
+
void seedQuESTDefault(QuESTEnv *env)
Seeds the random number generator with the (master node) current time and process ID.
Definition: QuEST.c:1614
+
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
+
void densmatr_initPlusState(Qureg targetQureg)
Definition: QuEST_cpu.c:1165
+
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:1143
+
void mixDamping(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:1283
+
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1369
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:156
-
void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:797
-
void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
Definition: QuEST.c:1163
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:519
-
void reportPauliHamil(PauliHamil hamil)
Print the PauliHamil to screen.
Definition: QuEST.c:1583
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
+
void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:796
+
void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
Definition: QuEST.c:1176
+
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
+
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:509
+
void reportPauliHamil(PauliHamil hamil)
Print the PauliHamil to screen.
Definition: QuEST.c:1598
+
void validateHamilParams(int numQubits, int numTerms, const char *caller)
void qasm_free(Qureg qureg)
Definition: QuEST_qasm.c:887
-
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:577
+
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:567
@ PAULI_I
Definition: QuEST.h:96
-
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:936
-
void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple control and target qubits.
Definition: QuEST.c:550
+
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:949
+
void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple control and target qubits.
Definition: QuEST.c:549
@ GATE_T
Definition: QuEST_qasm.h:24
@ GATE_PHASE_SHIFT
Definition: QuEST_qasm.h:32
void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit)
Definition: QuEST_qasm.c:208
-
DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
Definition: QuEST.c:1543
-
void validateStateVecQureg(Qureg qureg, const char *caller)
+
DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
Definition: QuEST.c:1558
+
void validateStateVecQureg(Qureg qureg, const char *caller)
void qasm_recordInitZero(Qureg qureg)
Definition: QuEST_qasm.c:428
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1335
-
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:534
+
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1348
+
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:524
void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:317
-
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:912
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:615
-
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:1301
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:571
-
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:299
-
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
-
void syncDiagonalOp(DiagonalOp op)
Update the GPU memory with the current values in op.real and op.imag.
Definition: QuEST.c:1516
-
void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
Definition: QuEST.c:1509
-
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:283
-
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
+
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:925
+
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
+
void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:614
+
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:1314
+
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:561
+
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:289
+
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
+
void syncDiagonalOp(DiagonalOp op)
Update the GPU memory with the current values in op.real and op.imag.
Definition: QuEST.c:1531
+
void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
Definition: QuEST.c:1524
+
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:282
+
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
void qasm_clearRecorded(Qureg qureg)
Definition: QuEST_qasm.c:864
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
void qasm_recordInitPlus(Qureg qureg)
Definition: QuEST_qasm.c:443
-
qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:953
+
qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:966
ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
Definition: QuEST_common.c:110
@ GATE_ROTATE_X
Definition: QuEST_qasm.h:27
+
int numSeeds
Definition: QuEST.h:367
-
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
-
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:1172
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3277
-
qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:1153
+
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
+
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:1185
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3316
+
qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:1166
+
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:265
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1362
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1317
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1373
+
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1328
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void getQuESTSeeds(QuESTEnv env, unsigned long int **seeds, int *numSeeds)
Obtain the seeds presently used in random number generation.
Definition: QuEST.c:1622
void clearRecordedQASM(Qureg qureg)
Clear all QASM so far recorded.
Definition: QuEST.c:95
-
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:985
+
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:998
@ GATE_ROTATE_Z
Definition: QuEST_qasm.h:29
-
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
Definition: QuEST.c:1178
-
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:349
-
void validateProb(qreal prob, const char *caller)
+
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
Definition: QuEST.c:1191
+
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:348
+
void validateProb(qreal prob, const char *caller)
@ GATE_SIGMA_Z
Definition: QuEST_qasm.h:23
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
-
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:1278
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:697
+
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
+
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:1291
+
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:701
Complex getConjugateScalar(Complex scalar)
Definition: QuEST_common.c:91
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3187
-
Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Computes the expected value of the diagonal operator op for state qureg.
Definition: QuEST.c:1215
+
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3226
+
Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Computes the expected value of the diagonal operator op for state qureg.
Definition: QuEST.c:1228
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
Definition: QuEST_common.c:105
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1600
-
void sGate(Qureg qureg, int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:466
+
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1611
+
void sGate(Qureg qureg, int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:465
void qasm_startRecording(Qureg qureg)
Definition: QuEST_qasm.c:85
-
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Overwrite the amplitudes of targetQureg with those from copyQureg.
Definition: QuEST.c:165
-
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
+
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Overwrite the amplitudes of targetQureg with those from copyQureg.
Definition: QuEST.c:164
+
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
void rotateY(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:199
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1115
-
void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
Definition: QuEST.c:1046
-
Information about the environment the program is running in.
Definition: QuEST.h:361
-
void setDensityAmps(Qureg qureg, qreal *reals, qreal *imags)
Set elements in the underlying state vector represenation of a density matrix.
Definition: QuEST.c:1017
-
void applyQFT(Qureg qureg, int *qubits, int numQubits)
Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
Definition: QuEST.c:867
-
PauliHamil createPauliHamilFromFile(char *fn)
Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
Definition: QuEST.c:1405
-
void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:744
-
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:511
-
void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
Definition: QuEST.c:1528
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3227
-
void statevec_pauliY(Qureg qureg, int targetQubit)
+
void rotateY(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:198
+
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1126
+
void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
Definition: QuEST.c:1059
+
Information about the environment the program is running in.
Definition: QuEST.h:362
+
void setDensityAmps(Qureg qureg, qreal *reals, qreal *imags)
Set elements in the underlying state vector represenation of a density matrix.
Definition: QuEST.c:1030
+
void applyQFT(Qureg qureg, int *qubits, int numQubits)
Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
Definition: QuEST.c:866
+
PauliHamil createPauliHamilFromFile(char *fn)
Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
Definition: QuEST.c:1420
+
void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:743
+
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:510
+
void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
Definition: QuEST.c:1543
+
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3266
+
void statevec_pauliY(Qureg qureg, int targetQubit)
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
void qasm_recordMultiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
Definition: QuEST_qasm.c:382
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
-
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:589
-
void validateNumPauliSumTerms(int numTerms, const char *caller)
-
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:390
+
void validateTwoQubitDepolProb(qreal prob, const char *caller)
+
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:579
+
void validateNumPauliSumTerms(int numTerms, const char *caller)
+
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:380
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
Definition: QuEST.c:686
-
void validateFileOpened(int opened, char *fn, const char *caller)
+
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
+
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
Definition: QuEST.c:685
+
void validateFileOpened(int opened, char *fn, const char *caller)
void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
Definition: QuEST_qasm.c:363
void stopRecordingQASM(Qureg qureg)
Disable QASM recording.
Definition: QuEST.c:91
-
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
Definition: QuEST.c:1008
-
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:588
-
void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:297
-
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:397
-
void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
Definition: QuEST.c:669
-
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:926
-
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:258
-
void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:564
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1335
-
void initComplexMatrixN(ComplexMatrixN m, qreal re[][1<< m.numQubits], qreal im[][1<< m.numQubits])
Initialises a ComplexMatrixN instance to have the passed real and imag values.
Definition: QuEST.c:1372
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:972
+
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
Definition: QuEST.c:1021
+
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:587
+
void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:296
+
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:387
+
void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
Definition: QuEST.c:668
+
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:939
+
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:248
+
void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:563
+
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1346
+
void initComplexMatrixN(ComplexMatrixN m, qreal re[][1<< m.numQubits], qreal im[][1<< m.numQubits])
Initialises a ComplexMatrixN instance to have the passed real and imag values.
Definition: QuEST.c:1386
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:985
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
-
qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
Computes the expected value of qureg under Hermitian operator hamil.
Definition: QuEST.c:1206
-
void validateVector(Vector vec, const char *caller)
-
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:331
+
qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
Computes the expected value of qureg under Hermitian operator hamil.
Definition: QuEST.c:1219
+
void validateVector(Vector vec, const char *caller)
+
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:330
qreal densmatr_calcTotalProb(Qureg qureg)
-
void rotateX(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:188
-
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
-
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:1024
+
void rotateX(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:187
+
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
+
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
+
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
+
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:1037
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:239
-
void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
Definition: QuEST.c:706
-
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:1224
-
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
+
void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
Definition: QuEST.c:705
+
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:1237
+
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit)
Definition: QuEST_qasm.c:224
-
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4406
+
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
+
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:901
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
@ GATE_SQRT_SWAP
Definition: QuEST_qasm.h:34
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3319
-
void pauliZ(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:455
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3358
+
void pauliZ(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:454
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
-
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
@ GATE_SIGMA_X
Definition: QuEST_qasm.h:21
void qasm_recordMeasurement(Qureg qureg, int measureQubit)
Definition: QuEST_qasm.c:411
void qasm_stopRecording(Qureg qureg)
Definition: QuEST_qasm.c:89
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1483
-
void applyDiagonalOp(Qureg qureg, DiagonalOp op)
Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
Definition: QuEST.c:1114
+
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1494
+
void applyDiagonalOp(Qureg qureg, DiagonalOp op)
Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
Definition: QuEST.c:1127
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:1080
-
void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST.c:1572
-
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:827
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
-
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
void swapGate(Qureg qureg, int qb1, int qb2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:628
-
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4228
+
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:1093
+
void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST.c:1587
+
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:840
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:85
+
void validateOneQubitDephaseProb(qreal prob, const char *caller)
+
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
void swapGate(Qureg qureg, int qb1, int qb2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:627
+
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4268
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:285
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
-
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise state-vector qureg by specifying all amplitudes.
Definition: QuEST.c:157
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1428
-
void validateControlState(int *controlState, int numControlQubits, const char *caller)
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4007
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
+
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:275
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
+
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise qureg by specifying all amplitudes.
Definition: QuEST.c:157
+
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1439
+
void validateControlState(int *controlState, int numControlQubits, const char *caller)
+
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4047
+
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
void qasm_recordInitClassical(Qureg qureg, long long int stateInd)
Definition: QuEST_qasm.c:471
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
+
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1248
int qasm_writeRecordedToFile(Qureg qureg, char *filename)
returns success of file write
Definition: QuEST_qasm.c:876
void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
Definition: QuEST_qasm.c:248
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1561
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:324
+
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1572
+
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:314
void writeRecordedQASMToFile(Qureg qureg, char *filename)
Writes recorded QASM to a file, throwing an error if inaccessible.
Definition: QuEST.c:103
-
int numRanks
Definition: QuEST.h:364
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
+
int numRanks
Definition: QuEST.h:365
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
void setConjugateMatrixN(ComplexMatrixN m)
Definition: QuEST_common.c:115
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:905
-
void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:576
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:689
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1493
+
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
+
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:918
+
void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:575
+
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:682
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1504
void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:301
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
-
int getNumQubits(Qureg qureg)
Returns the number of qubits represented by qureg.
Definition: QuEST.c:895
-
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:1137
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:424
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3678
+
int getNumQubits(Qureg qureg)
Returns the number of qubits represented by qureg.
Definition: QuEST.c:908
+
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
+
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
+
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:1150
+
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:414
+
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3718
void destroyQureg(Qureg qureg, QuESTEnv env)
Deallocate a Qureg, freeing its memory.
Definition: QuEST.c:77
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
-
void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
Definition: QuEST.c:849
+
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
+
void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
Definition: QuEST.c:848
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:314
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
-
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:583
-
void multiQubitNot(Qureg qureg, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
Definition: QuEST.c:537
-
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:1311
+
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:313
+
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
+
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:573
+
void multiQubitNot(Qureg qureg, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
Definition: QuEST.c:536
+
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:1324
qreal ** real
Definition: QuEST.h:189
-
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
-
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
Definition: QuEST.c:1563
-
void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Initialises the wavefunction amplitudes according to those specified in a file.
Definition: QuEST.c:1567
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:340
+
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
+
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
Definition: QuEST.c:1578
+
void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Initialises the wavefunction amplitudes according to those specified in a file.
Definition: QuEST.c:1582
+
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:330
void startRecordingQASM(Qureg qureg)
Enable QASM recording.
Definition: QuEST.c:87
-
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:548
-
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:1035
-
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
-
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:1090
+
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:538
+
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:1048
+
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
+
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:1103
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:331
-
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:292
-
void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:762
-
void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:405
+
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:321
+
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:282
+
unsigned long int * seeds
Definition: QuEST.h:366
+
void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:761
+
void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:404
void initClassicalState(Qureg qureg, long long int stateInd)
Initialise qureg into the classical state (also known as a "computational basis state") with index st...
Definition: QuEST.c:134
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
-
int getQuEST_PREC(void)
Definition: QuEST.c:1595
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3965
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
-
void pauliY(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:444
+
void validateOneQubitDepolProb(qreal prob, const char *caller)
+
int getQuEST_PREC(void)
Definition: QuEST.c:1610
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:4005
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
+
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
+
void pauliY(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:443
void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
Definition: QuEST_common.c:161
long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
Definition: QuEST_common.c:60
void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:342
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
Represents a system of qubits.
Definition: QuEST.h:322
void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
Definition: QuEST_qasm.c:325
-
void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:499
-
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:1247
-
void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:361
-
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:374
-
void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
-
void validateNumQubitsInMatrix(int numQubits, const char *caller)
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1646
+
void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:498
+
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:1260
+
void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:360
+
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:364
+
void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
+
void validateNumQubitsInMatrix(int numQubits, const char *caller)
+
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1657
qreal ** imag
Definition: QuEST.h:190
-
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
-
void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
Overwrites the entire DiagonalOp op with the given real and imag complex elements.
Definition: QuEST.c:1522
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_cpu.c:1366
-
void phaseShift(Qureg qureg, int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:488
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
+
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
+
void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
Overwrites the entire DiagonalOp op with the given real and imag complex elements.
Definition: QuEST.c:1537
+
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_cpu.c:1377
+
void phaseShift(Qureg qureg, int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:487
+
void validatePauliHamil(PauliHamil hamil, const char *caller)
-
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
-
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:356
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
-
void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:525
-
long long int getNumAmps(Qureg qureg)
Returns the number of complex amplitudes in a state-vector qureg.
Definition: QuEST.c:899
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:779
-
void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
Definition: QuEST.c:1535
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1525
-
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
+
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
+
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:346
+
void validateDiagOpInit(DiagonalOp op, const char *caller)
+
void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:524
+
long long int getNumAmps(Qureg qureg)
Returns the number of complex amplitudes in a state-vector qureg.
Definition: QuEST.c:912
+
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
+
void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:778
+
void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
Definition: QuEST.c:1550
+
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1536
+
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:312
-
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
+
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:302
+
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
int numQubits
Definition: QuEST.h:188
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
void pauliX(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:433
+
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
+
void pauliX(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:432
Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
Create a new Qureg which is an exact clone of the passed qureg, which can be either a state-vector or...
Definition: QuEST.c:64
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:1197
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1680
-
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
-
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
-
void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:270
-
void applyFullQFT(Qureg qureg)
Applies the quantum Fourier transform (QFT) to the entirety of qureg.
Definition: QuEST.c:877
-
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:1210
+
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1691
+
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
+
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
+
void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:269
+
void applyFullQFT(Qureg qureg)
Applies the quantum Fourier transform (QFT) to the entirety of qureg.
Definition: QuEST.c:876
+
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
-
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:410
-
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:368
+
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:400
+
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:358
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
-
void statevec_pauliX(Qureg qureg, int targetQubit)
+
void statevec_pauliX(Qureg qureg, int targetQubit)
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
-
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
+
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
@ GATE_S
Definition: QuEST_qasm.h:25
@ GATE_SWAP
Definition: QuEST_qasm.h:33
qreal real
Definition: QuEST.h:105
-
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
-
void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:999
+
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
+
void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:1012
Qureg createQureg(int numQubits, QuESTEnv env)
Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
Definition: QuEST.c:36
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1399
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:730
-
void tGate(Qureg qureg, int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:477
-
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
Definition: QuEST.c:653
+
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1414
+
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:743
+
void tGate(Qureg qureg, int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:476
+
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
Definition: QuEST.c:652
qreal imag
Definition: QuEST.h:106
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:4188
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3647
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
+
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:4228
+
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3687
+
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
+
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
@ GATE_SIGMA_Y
Definition: QuEST_qasm.h:22
void qasm_recordMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:666
-
void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
Definition: QuEST.c:832
+
void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
Definition: QuEST.c:831
void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit)
Definition: QuEST_qasm.c:196
-
void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:1290
+
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
+
void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:1303
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:70
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1730
+
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
+
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1741
void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
Definition: QuEST_qasm.c:279
-
void hadamard(Qureg qureg, int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:177
+
void hadamard(Qureg qureg, int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:176
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:362
-
void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general 2-by-2 matrix, which may be non-unitary.
Definition: QuEST.c:1071
-
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:347
-
void rotateZ(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:210
-
void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:374
+
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:352
+
void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general 2-by-2 matrix, which may be non-unitary.
Definition: QuEST.c:1084
+
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:337
+
void rotateZ(Qureg qureg, int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:209
+
void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:373
void initZeroState(Qureg qureg)
Initialise qureg into the zero state.
Definition: QuEST.c:113
-
void validateTrotterParams(int order, int reps, const char *caller)
+
void validateTrotterParams(int order, int reps, const char *caller)
void qasm_setup(Qureg *qureg)
Definition: QuEST_qasm.c:61
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:179
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:1145
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1279
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
+
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:1158
+
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1290
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Qureg createDensityQureg(int numQubits, QuESTEnv env)
Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
Definition: QuEST.c:50
-
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
+
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
@ GATE_ROTATE_Y
Definition: QuEST_qasm.h:28
-
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:318
-
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:1057
-
PauliHamil createPauliHamil(int numQubits, int numSumTerms)
Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
Definition: QuEST.c:1383
+
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:308
+
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:1070
+
PauliHamil createPauliHamil(int numQubits, int numSumTerms)
Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
Definition: QuEST.c:1398
void initPlusState(Qureg qureg)
Initialise qureg into the plus state.
Definition: QuEST.c:125
-
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:1188
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
-
void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:418
+
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:1201
+
void validateOneQubitDampingProb(qreal prob, const char *caller)
+
void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:417
void qasm_recordNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc funcName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:726
-
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
Definition: QuEST.c:389
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:640
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
+
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
Definition: QuEST.c:388
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:639
+
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:1321
+
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:1334
void printRecordedQASM(Qureg qureg)
Print recorded QASM to stdout.
Definition: QuEST.c:99
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
-
void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST.c:1579
-
DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
Definition: QuEST.c:1503
-
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:382
+
void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
+
void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST.c:1594
+
DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
Definition: QuEST.c:1518
+
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:372
qreal statevec_calcTotalProb(Qureg qureg)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
+
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
void qasm_recordPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:490
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
-
void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:233
-
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4305
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
+
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
+
void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:232
+
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4345
+
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
diff --git a/docs/QuEST_8h.html b/docs/QuEST_8h.html index 13a8f4e18..511bfaca4 100644 --- a/docs/QuEST_8h.html +++ b/docs/QuEST_8h.html @@ -27,7 +27,7 @@ @@ -190,6 +190,9 @@ void applyPhaseFuncOverrides (Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)  Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices. More...
  +void applyProjector (Qureg qureg, int qubit, int outcome) + Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection. More...
+  void applyQFT (Qureg qureg, int *qubits, int numQubits)  Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg. More...
  @@ -349,6 +352,9 @@ qreal getProbAmp (Qureg qureg, long long int index)  Get the probability of a state-vector at an index in the full state vector. More...
  +void getQuESTSeeds (QuESTEnv env, unsigned long int **seeds, int *numSeeds) + Obtain the seeds presently used in random number generation. More...
qreal getRealAmp (Qureg qureg, long long int index)  Get the real component of the complex probability amplitude at an index in the state vector. More...
  @@ -383,7 +389,7 @@  Initialise qureg into to a given pure state of an equivalent Hilbert dimension. More...
  void initStateFromAmps (Qureg qureg, qreal *reals, qreal *imags) - Initialise state-vector qureg by specifying all amplitudes. More...
+ Initialise qureg by specifying all amplitudes. More...
  void initZeroState (Qureg qureg)  Initialise qureg into the zero state. More...
@@ -508,12 +514,12 @@ void rotateZ (Qureg qureg, int rotQubit, qreal angle)  Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase shift gate). More...
  -void seedQuEST (unsigned long int *seedArray, int numSeeds) - Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed. More...
-  -void seedQuESTDefault (void) - Seed the Mersenne Twister used for random number generation in the QuEST environment with an example default seed. More...
-  +void seedQuEST (QuESTEnv *env, unsigned long int *seedArray, int numSeeds) + Seeds the random number generator with a custom array of key(s), overriding the default keys. More...
+  +void seedQuESTDefault (QuESTEnv *env) + Seeds the random number generator with the (master node) current time and process ID. More...
+  void setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)  Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags. More...
  @@ -526,8 +532,6 @@ void sGate (Qureg qureg, int targetQubit)  Apply the single-qubit S gate. More...
  -void SHARED_calcProbOfAllOutcomes (qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits) -  void sqrtSwapGate (Qureg qureg, int qb1, int qb2)  Performs a sqrt SWAP gate between qubit1 and qubit2. More...
  @@ -549,8 +553,6 @@ int syncQuESTSuccess (int successCode)  Performs a logical AND on all successCodes held by all processes. More...
  -void TEST_calcProbOfAllOutcomes (qreal *retProbs, Qureg qureg, int *qubits, int numQubits) -  void tGate (Qureg qureg, int targetQubit)  Apply the single-qubit T gate. More...
  @@ -568,88 +570,7 @@

The QuEST API. This file contains the comments used by doxygen for generating API doc.

Definition in file QuEST.h.

-

Function Documentation

- -

◆ SHARED_calcProbOfAllOutcomes()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SHARED_calcProbOfAllOutcomes (qrealoutcomeProbs,
Qureg qureg,
int * qubits,
int numQubits 
)
-
- -
-
- -

◆ TEST_calcProbOfAllOutcomes()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TEST_calcProbOfAllOutcomes (qrealretProbs,
Qureg qureg,
int * qubits,
int numQubits 
)
-
- -
-
- + diff --git a/docs/QuEST_8h_source.html b/docs/QuEST_8h_source.html index a3aa51ac6..c8cb06b80 100644 --- a/docs/QuEST_8h_source.html +++ b/docs/QuEST_8h_source.html @@ -27,7 +27,7 @@ @@ -179,546 +179,555 @@
352 
353 } Qureg;
354 
-
361 typedef struct QuESTEnv
-
362 {
-
363  int rank;
-
364  int numRanks;
-
365 } QuESTEnv;
-
366 
-
367 
-
368 
-
369 /*
-
370  * public functions
-
371  */
-
372 
-
529 Qureg createQureg(int numQubits, QuESTEnv env);
-
530 
-
623 Qureg createDensityQureg(int numQubits, QuESTEnv env);
-
624 
- -
645 
-
666 void destroyQureg(Qureg qureg, QuESTEnv env);
-
667 
-
721 ComplexMatrixN createComplexMatrixN(int numQubits);
-
722 
- -
740 
-
741 #ifndef __cplusplus
-
742 
-
764 void initComplexMatrixN(ComplexMatrixN m, qreal real[][1<<m.numQubits], qreal imag[][1<<m.numQubits]);
-
765 #endif
-
766 
-
802 PauliHamil createPauliHamil(int numQubits, int numSumTerms);
-
803 
-
810 void destroyPauliHamil(PauliHamil hamil);
-
811 
- -
859 
-
897 void initPauliHamil(PauliHamil hamil, qreal* coeffs, enum pauliOpType* codes);
-
898 
-
977 DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env);
-
978 
- -
992 
-
1011 void syncDiagonalOp(DiagonalOp op);
-
1012 
-
1039 void initDiagonalOp(DiagonalOp op, qreal* real, qreal* imag);
-
1040 
- -
1094 
- -
1138 
-
1185 void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems);
-
1186 
-
1223 void applyDiagonalOp(Qureg qureg, DiagonalOp op);
-
1224 
- -
1256 
-
1280 void reportState(Qureg qureg);
-
1281 
-
1289 void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank);
-
1290 
-
1297 void reportQuregParams(Qureg qureg);
-
1298 
-
1321 void reportPauliHamil(PauliHamil hamil);
-
1322 
-
1333 int getNumQubits(Qureg qureg);
-
1334 
-
1351 long long int getNumAmps(Qureg qureg);
-
1352 
-
1361 void initBlankState(Qureg qureg);
-
1362 
-
1375 void initZeroState(Qureg qureg);
-
1376 
-
1394 void initPlusState(Qureg qureg);
-
1395 
-
1431 void initClassicalState(Qureg qureg, long long int stateInd);
-
1432 
-
1451 void initPureState(Qureg qureg, Qureg pure);
-
1452 
-
1463 void initDebugState(Qureg qureg);
-
1464 
-
1490 void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags);
-
1491 
-
1537 void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps);
-
1538 
-
1559 void cloneQureg(Qureg targetQureg, Qureg copyQureg);
-
1560 
-
1595 void phaseShift(Qureg qureg, int targetQubit, qreal angle);
-
1596 
-
1640 void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle);
-
1641 
-
1683 void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle);
-
1684 
-
1723 void controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2);
-
1724 
-
1768 void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits);
-
1769 
-
1801 void sGate(Qureg qureg, int targetQubit);
-
1802 
-
1834 void tGate(Qureg qureg, int targetQubit);
-
1835 
-
1851 QuESTEnv createQuESTEnv(void);
-
1852 
-
1864 void destroyQuESTEnv(QuESTEnv env);
-
1865 
-
1875 void syncQuESTEnv(QuESTEnv env);
-
1876 
-
1885 int syncQuESTSuccess(int successCode);
-
1886 
-
1893 void reportQuESTEnv(QuESTEnv env);
-
1894 
-
1912 void getEnvironmentString(QuESTEnv env, char str[200]);
-
1913 
-
1939 void copyStateToGPU(Qureg qureg);
-
1940 
-
1966 void copyStateFromGPU(Qureg qureg);
-
1967 
-
1987 Complex getAmp(Qureg qureg, long long int index);
-
1988 
-
2008 qreal getRealAmp(Qureg qureg, long long int index);
-
2009 
-
2029 qreal getImagAmp(Qureg qureg, long long int index);
-
2030 
-
2050 qreal getProbAmp(Qureg qureg, long long int index);
-
2051 
-
2072 Complex getDensityAmp(Qureg qureg, long long int row, long long int col);
-
2073 
-
2099 qreal calcTotalProb(Qureg qureg);
-
2100 
-
2141 void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta);
-
2142 
-
2182 void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u);
-
2183 
-
2220 void rotateX(Qureg qureg, int rotQubit, qreal angle);
-
2221 
-
2259 void rotateY(Qureg qureg, int rotQubit, qreal angle);
-
2260 
-
2299 void rotateZ(Qureg qureg, int rotQubit, qreal angle);
-
2300 
-
2327 void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis);
-
2328 
-
2367 void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
2368 
-
2406 void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
2407 
-
2446 void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
-
2447 
-
2486 void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis);
-
2487 
-
2537 void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta);
-
2538 
-
2588 void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u);
-
2589 
-
2652 void multiControlledUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u);
-
2653 
-
2689 void pauliX(Qureg qureg, int targetQubit);
-
2690 
-
2724 void pauliY(Qureg qureg, int targetQubit);
-
2725 
-
2762 void pauliZ(Qureg qureg, int targetQubit);
-
2763 
-
2794 void hadamard(Qureg qureg, int targetQubit);
-
2795 
-
2838 void controlledNot(Qureg qureg, int controlQubit, int targetQubit);
-
2839 
-
2914 void multiControlledMultiQubitNot(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs);
-
2915 
-
2971 void multiQubitNot(Qureg qureg, int* targs, int numTargs);
-
2972 
-
3013 void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit);
-
3014 
-
3047 qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome);
-
3048 
-
3136 void calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits);
-
3137 // DEBUG
-
3138 void TEST_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits);
-
3139 void SHARED_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits);
-
3140 
-
3170 qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome);
-
3171 
-
3194 int measure(Qureg qureg, int measureQubit);
-
3195 
-
3219 int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb);
-
3220 
- -
3247 
- -
3300 
-
3324 void seedQuESTDefault(void);
-
3325 
-
3341 void seedQuEST(unsigned long int *seedArray, int numSeeds);
-
3342 
-
3351 void startRecordingQASM(Qureg qureg);
-
3352 
-
3362 void stopRecordingQASM(Qureg qureg);
-
3363 
-
3370 void clearRecordedQASM(Qureg qureg);
-
3371 
-
3379 void printRecordedQASM(Qureg qureg);
-
3380 
-
3390 void writeRecordedQASMToFile(Qureg qureg, char* filename);
-
3391 
-
3421 void mixDephasing(Qureg qureg, int targetQubit, qreal prob);
-
3422 
-
3453 void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob);
+
362 typedef struct QuESTEnv
+
363 {
+
364  int rank;
+
365  int numRanks;
+
366  unsigned long int* seeds;
+
367  int numSeeds;
+
368 } QuESTEnv;
+
369 
+
370 
+
371 
+
372 /*
+
373  * public functions
+
374  */
+
375 
+
532 Qureg createQureg(int numQubits, QuESTEnv env);
+
533 
+
626 Qureg createDensityQureg(int numQubits, QuESTEnv env);
+
627 
+ +
648 
+
669 void destroyQureg(Qureg qureg, QuESTEnv env);
+
670 
+
724 ComplexMatrixN createComplexMatrixN(int numQubits);
+
725 
+ +
743 
+
744 #ifndef __cplusplus
+
745 #ifndef _WIN32
+
746 
+
768 void initComplexMatrixN(ComplexMatrixN m, qreal real[][1<<m.numQubits], qreal imag[][1<<m.numQubits]);
+
769 #endif
+
770 #endif
+
771 
+
807 PauliHamil createPauliHamil(int numQubits, int numSumTerms);
+
808 
+
815 void destroyPauliHamil(PauliHamil hamil);
+
816 
+ +
864 
+
902 void initPauliHamil(PauliHamil hamil, qreal* coeffs, enum pauliOpType* codes);
+
903 
+
982 DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env);
+
983 
+ +
997 
+
1016 void syncDiagonalOp(DiagonalOp op);
+
1017 
+
1044 void initDiagonalOp(DiagonalOp op, qreal* real, qreal* imag);
+
1045 
+ +
1099 
+ +
1143 
+
1190 void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems);
+
1191 
+
1228 void applyDiagonalOp(Qureg qureg, DiagonalOp op);
+
1229 
+ +
1261 
+
1285 void reportState(Qureg qureg);
+
1286 
+
1294 void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank);
+
1295 
+
1302 void reportQuregParams(Qureg qureg);
+
1303 
+
1326 void reportPauliHamil(PauliHamil hamil);
+
1327 
+
1338 int getNumQubits(Qureg qureg);
+
1339 
+
1356 long long int getNumAmps(Qureg qureg);
+
1357 
+
1366 void initBlankState(Qureg qureg);
+
1367 
+
1380 void initZeroState(Qureg qureg);
+
1381 
+
1399 void initPlusState(Qureg qureg);
+
1400 
+
1436 void initClassicalState(Qureg qureg, long long int stateInd);
+
1437 
+
1456 void initPureState(Qureg qureg, Qureg pure);
+
1457 
+
1468 void initDebugState(Qureg qureg);
+
1469 
+
1495 void initStateFromAmps(Qureg qureg, qreal* reals, qreal* imags);
+
1496 
+
1542 void setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps);
+
1543 
+
1564 void cloneQureg(Qureg targetQureg, Qureg copyQureg);
+
1565 
+
1600 void phaseShift(Qureg qureg, int targetQubit, qreal angle);
+
1601 
+
1645 void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle);
+
1646 
+
1688 void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle);
+
1689 
+
1728 void controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2);
+
1729 
+
1773 void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits);
+
1774 
+
1806 void sGate(Qureg qureg, int targetQubit);
+
1807 
+
1839 void tGate(Qureg qureg, int targetQubit);
+
1840 
+
1856 QuESTEnv createQuESTEnv(void);
+
1857 
+
1869 void destroyQuESTEnv(QuESTEnv env);
+
1870 
+
1880 void syncQuESTEnv(QuESTEnv env);
+
1881 
+
1890 int syncQuESTSuccess(int successCode);
+
1891 
+
1898 void reportQuESTEnv(QuESTEnv env);
+
1899 
+
1917 void getEnvironmentString(QuESTEnv env, char str[200]);
+
1918 
+
1944 void copyStateToGPU(Qureg qureg);
+
1945 
+
1971 void copyStateFromGPU(Qureg qureg);
+
1972 
+
1992 Complex getAmp(Qureg qureg, long long int index);
+
1993 
+
2013 qreal getRealAmp(Qureg qureg, long long int index);
+
2014 
+
2034 qreal getImagAmp(Qureg qureg, long long int index);
+
2035 
+
2055 qreal getProbAmp(Qureg qureg, long long int index);
+
2056 
+
2077 Complex getDensityAmp(Qureg qureg, long long int row, long long int col);
+
2078 
+
2104 qreal calcTotalProb(Qureg qureg);
+
2105 
+
2146 void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta);
+
2147 
+
2187 void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u);
+
2188 
+
2225 void rotateX(Qureg qureg, int rotQubit, qreal angle);
+
2226 
+
2264 void rotateY(Qureg qureg, int rotQubit, qreal angle);
+
2265 
+
2304 void rotateZ(Qureg qureg, int rotQubit, qreal angle);
+
2305 
+
2332 void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis);
+
2333 
+
2372 void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
+
2373 
+
2411 void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
+
2412 
+
2451 void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle);
+
2452 
+
2491 void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis);
+
2492 
+
2542 void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta);
+
2543 
+
2593 void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u);
+
2594 
+
2657 void multiControlledUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u);
+
2658 
+
2694 void pauliX(Qureg qureg, int targetQubit);
+
2695 
+
2729 void pauliY(Qureg qureg, int targetQubit);
+
2730 
+
2767 void pauliZ(Qureg qureg, int targetQubit);
+
2768 
+
2799 void hadamard(Qureg qureg, int targetQubit);
+
2800 
+
2843 void controlledNot(Qureg qureg, int controlQubit, int targetQubit);
+
2844 
+
2919 void multiControlledMultiQubitNot(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs);
+
2920 
+
2976 void multiQubitNot(Qureg qureg, int* targs, int numTargs);
+
2977 
+
3018 void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit);
+
3019 
+
3052 qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome);
+
3053 
+
3141 void calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits);
+
3142 
+
3176 qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome);
+
3177 
+
3201 int measure(Qureg qureg, int measureQubit);
+
3202 
+
3227 int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb);
+
3228 
+ +
3255 
+ +
3308 
+
3331 void seedQuESTDefault(QuESTEnv *env);
+
3332 
+
3360 void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds);
+
3361 
+
3404 void getQuESTSeeds(QuESTEnv env, unsigned long int** seeds, int* numSeeds);
+
3405 
+
3414 void startRecordingQASM(Qureg qureg);
+
3415 
+
3425 void stopRecordingQASM(Qureg qureg);
+
3426 
+
3433 void clearRecordedQASM(Qureg qureg);
+
3434 
+
3442 void printRecordedQASM(Qureg qureg);
+
3443 
+
3453 void writeRecordedQASMToFile(Qureg qureg, char* filename);
3454 
-
3496 void mixDepolarising(Qureg qureg, int targetQubit, qreal prob);
-
3497 
-
3534 void mixDamping(Qureg qureg, int targetQubit, qreal prob);
-
3535 
-
3601 void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob);
-
3602 
-
3642 void mixPauli(Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ);
-
3643 
-
3664 void mixDensityMatrix(Qureg combineQureg, qreal prob, Qureg otherQureg);
+
3484 void mixDephasing(Qureg qureg, int targetQubit, qreal prob);
+
3485 
+
3516 void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob);
+
3517 
+
3559 void mixDepolarising(Qureg qureg, int targetQubit, qreal prob);
+
3560 
+
3597 void mixDamping(Qureg qureg, int targetQubit, qreal prob);
+
3598 
+
3664 void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob);
3665 
-
3692 qreal calcPurity(Qureg qureg);
-
3693 
-
3724 qreal calcFidelity(Qureg qureg, Qureg pureState);
-
3725 
-
3768 void swapGate(Qureg qureg, int qubit1, int qubit2);
-
3769 
-
3770 
-
3816 void sqrtSwapGate(Qureg qureg, int qb1, int qb2);
-
3817 
-
3877 void multiStateControlledUnitary(Qureg qureg, int* controlQubits, int* controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u);
-
3878 
-
3912 void multiRotateZ(Qureg qureg, int* qubits, int numQubits, qreal angle);
-
3913 
-
3967 void multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle);
-
3968 
-
4037 void multiControlledMultiRotateZ(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, int numTargets, qreal angle);
-
4038 
-
4138 void multiControlledMultiRotatePauli(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle);
-
4139 
-
4189 qreal calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace);
-
4190 
-
4244 qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace);
-
4245 
-
4285 qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace);
-
4286 
-
4353 void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
4354 
-
4420 void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
4421 
-
4499 void multiControlledTwoQubitUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
4500 
-
4582 void multiQubitUnitary(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u);
-
4583 
-
4655 void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targs, int numTargs, ComplexMatrixN u);
-
4656 
-
4744 void multiControlledMultiQubitUnitary(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u);
-
4745 
-
4789 void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps);
-
4790 
-
4828 void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps);
-
4829 
-
4878 void mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps);
-
4879 
- -
4912 
-
4936 void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out);
-
4937 
-
4995 void applyPauliSum(Qureg inQureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg);
-
4996 
-
5039 void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg);
-
5040 
-
5119 void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps);
-
5120 
-
5140 void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u);
-
5141 
-
5192 void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
-
5193 
-
5260 void applyMatrixN(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u);
-
5261 
-
5313 void applyMultiControlledMatrixN(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u);
-
5314 
-
5354 void invalidQuESTInputError(const char* errMsg, const char* errFunc);
-
5355 
-
5356 #ifndef __cplusplus
-
5357  // hide this function from doxygen
-
5359 
- -
5398  int numQubits, qreal re[][1<<numQubits], qreal im[][1<<numQubits],
-
5399  qreal** reStorage, qreal** imStorage);
-
5400 #endif
-
5401 
-
5403 // hide this function from doxygen
-
5405 #define UNPACK_ARR(...) __VA_ARGS__
-
5406 
-
5408 #ifndef __cplusplus
-
5409 
-
5456 #define getStaticComplexMatrixN(numQubits, re, im) \
-
5457  bindArraysToStackComplexMatrixN( \
-
5458  numQubits, \
-
5459  (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR re, \
-
5460  (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR im, \
-
5461  (double*[1<<numQubits]) {NULL}, (double*[1<<numQubits]) {NULL} \
-
5462  )
-
5463 #endif
-
5464 
-
5571 void applyPhaseFunc(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms);
-
5572 
-
5682 void applyPhaseFuncOverrides(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, qreal* overridePhases, int numOverrides);
-
5683 
-
5843 void applyMultiVarPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg);
-
5844 
-
5925 void applyMultiVarPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg, long long int* overrideInds, qreal* overridePhases, int numOverrides);
-
5926 
-
6065 void applyNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode);
-
6066 
-
6138 void applyNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int* overrideInds, qreal* overridePhases, int numOverrides);
-
6139 
-
6251 void applyParamNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams);
-
6252 
-
6326 void applyParamNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams, long long int* overrideInds, qreal* overridePhases, int numOverrides);
-
6327 
-
6420 void applyFullQFT(Qureg qureg);
-
6421 
-
6536 void applyQFT(Qureg qureg, int* qubits, int numQubits);
-
6537 
-
6538 // end prevention of C++ name mangling
-
6539 #ifdef __cplusplus
-
6540 }
-
6541 #endif
-
6542 
-
6543 #endif // QUEST_H
-
6544 
+
3705 void mixPauli(Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ);
+
3706 
+
3727 void mixDensityMatrix(Qureg combineQureg, qreal prob, Qureg otherQureg);
+
3728 
+
3755 qreal calcPurity(Qureg qureg);
+
3756 
+
3787 qreal calcFidelity(Qureg qureg, Qureg pureState);
+
3788 
+
3831 void swapGate(Qureg qureg, int qubit1, int qubit2);
+
3832 
+
3833 
+
3879 void sqrtSwapGate(Qureg qureg, int qb1, int qb2);
+
3880 
+
3940 void multiStateControlledUnitary(Qureg qureg, int* controlQubits, int* controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u);
+
3941 
+
3975 void multiRotateZ(Qureg qureg, int* qubits, int numQubits, qreal angle);
+
3976 
+
4030 void multiRotatePauli(Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle);
+
4031 
+
4100 void multiControlledMultiRotateZ(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, int numTargets, qreal angle);
+
4101 
+
4201 void multiControlledMultiRotatePauli(Qureg qureg, int* controlQubits, int numControls, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle);
+
4202 
+
4252 qreal calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace);
+
4253 
+
4307 qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace);
+
4308 
+
4348 qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace);
+
4349 
+
4416 void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
+
4417 
+
4483 void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
+
4484 
+
4562 void multiControlledTwoQubitUnitary(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
+
4563 
+
4645 void multiQubitUnitary(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u);
+
4646 
+
4718 void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targs, int numTargs, ComplexMatrixN u);
+
4719 
+
4807 void multiControlledMultiQubitUnitary(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u);
+
4808 
+
4852 void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps);
+
4853 
+
4891 void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps);
+
4892 
+
4941 void mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps);
+
4942 
+ +
4975 
+
4999 void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out);
+
5000 
+
5058 void applyPauliSum(Qureg inQureg, enum pauliOpType* allPauliCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg);
+
5059 
+
5102 void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg);
+
5103 
+
5182 void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps);
+
5183 
+
5203 void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u);
+
5204 
+
5255 void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u);
+
5256 
+
5323 void applyMatrixN(Qureg qureg, int* targs, int numTargs, ComplexMatrixN u);
+
5324 
+
5376 void applyMultiControlledMatrixN(Qureg qureg, int* ctrls, int numCtrls, int* targs, int numTargs, ComplexMatrixN u);
+
5377 
+
5417 void invalidQuESTInputError(const char* errMsg, const char* errFunc);
+
5418 
+
5419 #ifndef __cplusplus
+
5420 #ifndef _WIN32
+
5421  // hide this function from doxygen
+
5423 
+ +
5462  int numQubits, qreal re[][1<<numQubits], qreal im[][1<<numQubits],
+
5463  qreal** reStorage, qreal** imStorage);
+
5464 #endif
+
5465 #endif
+
5466 
+
5468 // hide this function from doxygen
+
5470 #define UNPACK_ARR(...) __VA_ARGS__
+
5471 
+
5473 #ifndef __cplusplus
+
5474 
+
5521 #define getStaticComplexMatrixN(numQubits, re, im) \
+
5522  bindArraysToStackComplexMatrixN( \
+
5523  numQubits, \
+
5524  (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR re, \
+
5525  (qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR im, \
+
5526  (double*[1<<numQubits]) {NULL}, (double*[1<<numQubits]) {NULL} \
+
5527  )
+
5528 #endif
+
5529 
+
5636 void applyPhaseFunc(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms);
+
5637 
+
5747 void applyPhaseFuncOverrides(Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, qreal* overridePhases, int numOverrides);
+
5748 
+
5908 void applyMultiVarPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg);
+
5909 
+
5990 void applyMultiVarPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int* numTermsPerReg, long long int* overrideInds, qreal* overridePhases, int numOverrides);
+
5991 
+
6130 void applyNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode);
+
6131 
+
6203 void applyNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int* overrideInds, qreal* overridePhases, int numOverrides);
+
6204 
+
6321 void applyParamNamedPhaseFunc(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams);
+
6322 
+
6396 void applyParamNamedPhaseFuncOverrides(Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal* params, int numParams, long long int* overrideInds, qreal* overridePhases, int numOverrides);
+
6397 
+
6490 void applyFullQFT(Qureg qureg);
+
6491 
+
6606 void applyQFT(Qureg qureg, int* qubits, int numQubits);
+
6607 
+
6630 void applyProjector(Qureg qureg, int qubit, int outcome);
+
6631 
+
6632 // end prevention of C++ name mangling
+
6633 #ifdef __cplusplus
+
6634 }
+
6635 #endif
+
6636 
+
6637 #endif // QUEST_H
+
6638 
-
void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:245
-
void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:1237
+
void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:244
+
void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:1250
@ INVERSE_PRODUCT
Definition: QuEST.h:233
-
qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:919
+
qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:932
void initBlankState(Qureg qureg)
Initialises a qureg to have all-zero-amplitudes.
Definition: QuEST.c:119
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
+
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:727
-
void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
Definition: QuEST.c:1101
-
void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:257
-
void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:221
-
void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:814
-
void reportQuregParams(Qureg qureg)
Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.
Definition: QuEST_common.c:247
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:39
-
void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
Definition: QuEST.c:1489
+
void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:726
+
void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
Definition: QuEST.c:1114
+
void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:256
+
void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:220
+
void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:813
+
void reportQuregParams(Qureg qureg)
Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.
Definition: QuEST_common.c:237
+
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:45
+
void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
Definition: QuEST.c:1504
qreal real[4][4]
Definition: QuEST.h:177
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
void initPureState(Qureg qureg, Qureg pure)
Initialise qureg into to a given pure state of an equivalent Hilbert dimension.
Definition: QuEST.c:145
+
void applyProjector(Qureg qureg, int qubit, int outcome)
Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection.
Definition: QuEST.c:888
@ PAULI_Z
Definition: QuEST.h:96
-
void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:602
+
void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:601
@ DISTANCE
Definition: QuEST.h:234
-
void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:1259
-
int rank
Definition: QuEST.h:363
-
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:1130
-
void mixDamping(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:1270
-
void destroyComplexMatrixN(ComplexMatrixN matr)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1356
+
void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:1272
+
int rank
Definition: QuEST.h:364
+
void seedQuESTDefault(QuESTEnv *env)
Seeds the random number generator with the (master node) current time and process ID.
Definition: QuEST.c:1614
+
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:1143
+
void mixDamping(Qureg qureg, int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:1283
+
void destroyComplexMatrixN(ComplexMatrixN matr)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1369
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:304
-
void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:797
-
void calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
Definition: QuEST.c:1163
-
void reportPauliHamil(PauliHamil hamil)
Print the PauliHamil to screen.
Definition: QuEST.c:1583
+
void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:796
+
void calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
Definition: QuEST.c:1176
+
void reportPauliHamil(PauliHamil hamil)
Print the PauliHamil to screen.
Definition: QuEST.c:1598
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
@ PAULI_I
Definition: QuEST.h:96
-
void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple control and target qubits.
Definition: QuEST.c:550
-
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:936
-
DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
Definition: QuEST.c:1543
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1335
-
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:912
-
void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:615
-
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:1301
-
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
-
void syncDiagonalOp(DiagonalOp op)
Update the GPU memory with the current values in op.real and op.imag.
Definition: QuEST.c:1516
-
void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
Definition: QuEST.c:1509
+
void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple control and target qubits.
Definition: QuEST.c:549
+
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:949
+
DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
Definition: QuEST.c:1558
+
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1348
+
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:925
+
void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:614
+
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:1314
+
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
+
void syncDiagonalOp(DiagonalOp op)
Update the GPU memory with the current values in op.real and op.imag.
Definition: QuEST.c:1531
+
void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
Definition: QuEST.c:1524
qreal z
Definition: QuEST.h:200
-
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:283
-
qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:953
+
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:282
+
qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:966
+
int numSeeds
Definition: QuEST.h:367
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
-
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:1172
-
qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:1153
+
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:1185
+
qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:1166
ComplexArray deviceOperator
A copy of the elements stored persistently on the GPU.
Definition: QuEST.h:312
+
void getQuESTSeeds(QuESTEnv env, unsigned long int **seeds, int *numSeeds)
Obtain the seeds presently used in random number generation.
Definition: QuEST.c:1622
void clearRecordedQASM(Qureg qureg)
Clear all QASM so far recorded.
Definition: QuEST.c:95
-
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:985
-
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
Definition: QuEST.c:1178
-
void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:349
+
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:998
+
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
Definition: QuEST.c:1191
+
void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:348
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:306
ComplexArray deviceStateVec
Storage for wavefunction amplitudes in the GPU version.
Definition: QuEST.h:346
@ NORM
Definition: QuEST.h:232
-
void seedQuEST(unsigned long int *seedArray, int numSeeds)
Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defi...
Definition: QuEST_common.c:222
-
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:1278
-
Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Computes the expected value of the diagonal operator op for state qureg.
Definition: QuEST.c:1215
-
void sGate(Qureg qureg, int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:466
-
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Overwrite the amplitudes of targetQureg with those from copyQureg.
Definition: QuEST.c:165
+
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:1291
+
Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Computes the expected value of the diagonal operator op for state qureg.
Definition: QuEST.c:1228
+
void sGate(Qureg qureg, int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:465
+
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Overwrite the amplitudes of targetQureg with those from copyQureg.
Definition: QuEST.c:164
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
-
void rotateY(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:199
-
void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
Definition: QuEST.c:1046
-
Information about the environment the program is running in.
Definition: QuEST.h:361
-
void applyQFT(Qureg qureg, int *qubits, int numQubits)
Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
Definition: QuEST.c:867
+
void rotateY(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:198
+
void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
Definition: QuEST.c:1059
+
Information about the environment the program is running in.
Definition: QuEST.h:362
+
void applyQFT(Qureg qureg, int *qubits, int numQubits)
Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
Definition: QuEST.c:866
@ UNSIGNED
Definition: QuEST.h:269
-
PauliHamil createPauliHamilFromFile(char *fn)
Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
Definition: QuEST.c:1405
-
void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:744
-
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:511
-
void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
Definition: QuEST.c:1528
-
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:661
+
PauliHamil createPauliHamilFromFile(char *fn)
Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
Definition: QuEST.c:1420
+
void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:743
+
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:510
+
void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
Definition: QuEST.c:1543
+
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:652
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
@ INVERSE_DISTANCE
Definition: QuEST.h:234
#define qreal
-
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
Definition: QuEST.c:686
+
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
Definition: QuEST.c:685
void stopRecordingQASM(Qureg qureg)
Disable QASM recording.
Definition: QuEST.c:91
-
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
Definition: QuEST.c:1008
-
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:588
-
void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:297
-
void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
Definition: QuEST.c:669
+
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
Definition: QuEST.c:1021
+
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:587
+
void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:296
+
void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
Definition: QuEST.c:668
@ PAULI_X
Definition: QuEST.h:96
-
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:926
-
void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:564
-
void reportState(Qureg qureg)
Print the current state vector of probability amplitudes for a set of qubits to file.
Definition: QuEST_common.c:229
-
void initComplexMatrixN(ComplexMatrixN m, qreal real[][1<< m.numQubits], qreal imag[][1<< m.numQubits])
Initialises a ComplexMatrixN instance to have the passed real and imag values.
Definition: QuEST.c:1372
-
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:972
+
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:939
+
void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:563
+
void reportState(Qureg qureg)
Print the current state vector of probability amplitudes for a set of qubits to file.
Definition: QuEST_common.c:219
+
void initComplexMatrixN(ComplexMatrixN m, qreal real[][1<< m.numQubits], qreal imag[][1<< m.numQubits])
Initialises a ComplexMatrixN instance to have the passed real and imag values.
Definition: QuEST.c:1386
+
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:985
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
-
qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
Computes the expected value of qureg under Hermitian operator hamil.
Definition: QuEST.c:1206
-
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:331
-
void rotateX(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:188
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
-
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:1024
+
qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
Computes the expected value of qureg under Hermitian operator hamil.
Definition: QuEST.c:1219
+
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:330
+
void rotateX(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:187
+
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
+
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:1037
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
-
void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
Definition: QuEST.c:706
-
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:1224
+
void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
Definition: QuEST.c:705
+
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:1237
qreal y
Definition: QuEST.h:200
qreal imag[2][2]
Definition: QuEST.h:140
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
qreal x
Definition: QuEST.h:200
-
void pauliZ(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:455
+
void pauliZ(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:454
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void applyDiagonalOp(Qureg qureg, DiagonalOp op)
Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
Definition: QuEST.c:1114
+
void applyDiagonalOp(Qureg qureg, DiagonalOp op)
Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
Definition: QuEST.c:1127
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:1080
-
void swapGate(Qureg qureg, int qubit1, int qubit2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:628
+
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:1093
+
void swapGate(Qureg qureg, int qubit1, int qubit2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:627
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise state-vector qureg by specifying all amplitudes.
Definition: QuEST.c:157
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:36
+
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise qureg by specifying all amplitudes.
Definition: QuEST.c:157
+
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:42
@ SCALED_PRODUCT
Definition: QuEST.h:233
void writeRecordedQASMToFile(Qureg qureg, char *filename)
Writes recorded QASM to a file, throwing an error if inaccessible.
Definition: QuEST.c:103
-
int numRanks
Definition: QuEST.h:364
+
int numRanks
Definition: QuEST.h:365
qreal imag[4][4]
Definition: QuEST.h:178
-
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:905
-
void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:576
+
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:918
+
void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:575
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
@ PAULI_Y
Definition: QuEST.h:96
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
-
int getNumQubits(Qureg qureg)
Returns the number of qubits represented by qureg.
Definition: QuEST.c:895
-
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:1137
+
int getNumQubits(Qureg qureg)
Returns the number of qubits represented by qureg.
Definition: QuEST.c:908
+
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:1150
void destroyQureg(Qureg qureg, QuESTEnv env)
Deallocate a Qureg, freeing its memory.
Definition: QuEST.c:77
-
void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
Definition: QuEST.c:849
+
void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
Definition: QuEST.c:848
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
-
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:314
-
void multiQubitNot(Qureg qureg, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
Definition: QuEST.c:537
-
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:1311
+
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:313
+
void multiQubitNot(Qureg qureg, int *targs, int numTargs)
Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
Definition: QuEST.c:536
+
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:1324
qreal ** real
Definition: QuEST.h:189
-
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
Definition: QuEST.c:1563
+
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
Definition: QuEST.c:1578
QASMLogger * qasmLog
Storage for generated QASM output.
Definition: QuEST.h:351
qreal * secondLevelReduction
Definition: QuEST.h:348
void startRecordingQASM(Qureg qureg)
Enable QASM recording.
Definition: QuEST.c:87
-
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:1035
-
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:1090
-
void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:762
-
void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:405
+
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:1048
+
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:1103
+
unsigned long int * seeds
Definition: QuEST.h:366
+
void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:761
+
void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:404
void initClassicalState(Qureg qureg, long long int stateInd)
Initialise qureg into the classical state (also known as a "computational basis state") with index st...
Definition: QuEST.c:134
-
void pauliY(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:444
+
void pauliY(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:443
@ INVERSE_NORM
Definition: QuEST.h:232
Represents a system of qubits.
Definition: QuEST.h:322
-
void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:499
-
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:1247
-
void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:361
+
void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:498
+
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:1260
+
void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:360
qreal ** imag
Definition: QuEST.h:190
-
void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
Overwrites the entire DiagonalOp op with the given real and imag complex elements.
Definition: QuEST.c:1522
-
void phaseShift(Qureg qureg, int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:488
+
void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
Overwrites the entire DiagonalOp op with the given real and imag complex elements.
Definition: QuEST.c:1537
+
void phaseShift(Qureg qureg, int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:487
@ PRODUCT
Definition: QuEST.h:233
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
-
void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:525
+
void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:524
qreal real[2][2]
Definition: QuEST.h:139
-
long long int getNumAmps(Qureg qureg)
Returns the number of complex amplitudes in a state-vector qureg.
Definition: QuEST.c:899
-
void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:779
-
void seedQuESTDefault(void)
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
+
long long int getNumAmps(Qureg qureg)
Returns the number of complex amplitudes in a state-vector qureg.
Definition: QuEST.c:912
+
void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:778
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
-
void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
Definition: QuEST.c:1535
+
void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
Definition: QuEST.c:1550
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
+
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
int numQubits
Definition: QuEST.h:188
-
void pauliX(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:433
+
void pauliX(Qureg qureg, int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:432
Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
Create a new Qureg which is an exact clone of the passed qureg, which can be either a state-vector or...
Definition: QuEST.c:64
-
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:1197
-
void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:270
-
void applyFullQFT(Qureg qureg)
Applies the quantum Fourier transform (QFT) to the entirety of qureg.
Definition: QuEST.c:877
+
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:1210
+
void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:269
+
void applyFullQFT(Qureg qureg)
Applies the quantum Fourier transform (QFT) to the entirety of qureg.
Definition: QuEST.c:876
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
-
void SHARED_calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
+
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
void mixDensityMatrix(Qureg combineQureg, qreal prob, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:999
+
void mixDensityMatrix(Qureg combineQureg, qreal prob, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:1012
Qureg createQureg(int numQubits, QuESTEnv env)
Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
Definition: QuEST.c:36
-
void destroyPauliHamil(PauliHamil hamil)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1399
-
void tGate(Qureg qureg, int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:477
-
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
Definition: QuEST.c:653
+
void destroyPauliHamil(PauliHamil hamil)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1414
+
void tGate(Qureg qureg, int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:476
+
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
Definition: QuEST.c:652
qreal imag
Definition: QuEST.h:106
-
void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
Definition: QuEST.c:832
+
void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
Definition: QuEST.c:831
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
-
void mixPauli(Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:1290
-
void TEST_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
void hadamard(Qureg qureg, int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:177
+
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
+
void mixPauli(Qureg qureg, int targetQubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:1303
+
void hadamard(Qureg qureg, int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:176
Represents one complex number.
Definition: QuEST.h:103
-
void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general 2-by-2 matrix, which may be non-unitary.
Definition: QuEST.c:1071
+
void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Apply a general 2-by-2 matrix, which may be non-unitary.
Definition: QuEST.c:1084
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
-
void rotateZ(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:210
+
void rotateZ(Qureg qureg, int rotQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:209
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:374
+
void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:373
void initZeroState(Qureg qureg)
Initialise qureg into the zero state.
Definition: QuEST.c:113
-
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:1145
+
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:1158
Qureg createDensityQureg(int numQubits, QuESTEnv env)
Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
Definition: QuEST.c:50
qreal * firstLevelReduction
Storage for reduction of probabilities on GPU.
Definition: QuEST.h:348
-
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:1057
-
PauliHamil createPauliHamil(int numQubits, int numSumTerms)
Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
Definition: QuEST.c:1383
+
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:1070
+
PauliHamil createPauliHamil(int numQubits, int numSumTerms)
Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
Definition: QuEST.c:1398
void initPlusState(Qureg qureg)
Initialise qureg into the plus state.
Definition: QuEST.c:125
-
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:1188
-
void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:418
-
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
Definition: QuEST.c:389
-
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:640
+
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:1201
+
void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:417
+
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
Definition: QuEST.c:388
+
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:639
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:1321
+
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:1334
void printRecordedQASM(Qureg qureg)
Print recorded QASM to stdout.
Definition: QuEST.c:99
-
void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST.c:1579
-
DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
Definition: QuEST.c:1503
+
void reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST.c:1594
+
DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
Definition: QuEST.c:1518
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:233
+
void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:232
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
diff --git a/docs/QuEST__common_8c.html b/docs/QuEST__common_8c.html index 49ed2559f..2712f4a08 100644 --- a/docs/QuEST__common_8c.html +++ b/docs/QuEST__common_8c.html @@ -27,7 +27,7 @@ @@ -158,9 +158,6 @@ void reportState (Qureg qureg)  Print the current state vector of probability amplitudes for a set of qubits to file. More...
  -void seedQuEST (unsigned long int *seedArray, int numSeeds) - numSeeds <= 64 More...
-  void setConjugateMatrixN (ComplexMatrixN m)   void shiftIndices (int *indices, int numIndices, int shift) @@ -287,7 +284,7 @@

qreal imArr_[1<<(numQubits)][1<<(numQubits)]; \
macro_initialiseStackComplexMatrixN(matrix, (numQubits), reArr_, imArr_);
-

Definition at line 683 of file QuEST_common.c.

+

Definition at line 675 of file QuEST_common.c.

@@ -333,7 +330,7 @@

qreal* imStorage_[1<<(numQubits)]; \
matrix = bindArraysToStackComplexMatrixN((numQubits), real, imag, reStorage_, imStorage_);
-

Definition at line 677 of file QuEST_common.c.

+

Definition at line 669 of file QuEST_common.c.

@@ -395,7 +392,7 @@

ops[n].imag[i][j]*ops[n].real[k][l]; \
}
-

Definition at line 595 of file QuEST_common.c.

+

Definition at line 585 of file QuEST_common.c.

@@ -473,74 +470,74 @@

-

Definition at line 836 of file QuEST_common.c.

-
836  {
-
837 
-
838  int densShift = qureg.numQubitsRepresented;
-
839 
-
840  // start with top/left-most qubit, work down
-
841  for (int q=numQubits-1; q >= 0; q--) {
-
842 
-
843  // H
-
844  statevec_hadamard(qureg, qubits[q]);
-
845  if (qureg.isDensityMatrix)
-
846  statevec_hadamard(qureg, qubits[q] + densShift);
-
847  qasm_recordGate(qureg, GATE_HADAMARD, qubits[q]);
-
848 
-
849  if (q == 0)
-
850  break;
-
851 
-
852  // succession of C-phases, control on qubits[q], targeting each of
-
853  // qubits[q-1], qubits[q-1], ... qubits[0]. This can be expressed by
-
854  // a single invocation of applyNamedPhaseFunc product
+

Definition at line 849 of file QuEST_common.c.

+
849  {
+
850 
+
851  int densShift = qureg.numQubitsRepresented;
+
852 
+
853  // start with top/left-most qubit, work down
+
854  for (int q=numQubits-1; q >= 0; q--) {
855 
-
856  int numRegs = 2;
-
857  int numQubitsPerReg[2] = {q, 1};
-
858  int regs[q+1];
-
859  for (int i=0; i<q+1; i++)
-
860  regs[i] = qubits[i]; // qubits[q] is in own register
+
856  // H
+
857  statevec_hadamard(qureg, qubits[q]);
+
858  if (qureg.isDensityMatrix)
+
859  statevec_hadamard(qureg, qubits[q] + densShift);
+
860  qasm_recordGate(qureg, GATE_HADAMARD, qubits[q]);
861 
-
862  int numParams = 1;
-
863  qreal params[1] = { M_PI / (1 << q) };
+
862  if (q == 0)
+
863  break;
864 
-
865  int conj = 0;
- -
867  qureg, regs, numQubitsPerReg, numRegs,
-
868  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
869  NULL, NULL, 0,
-
870  conj);
-
871  if (qureg.isDensityMatrix) {
-
872  conj = 1;
-
873  shiftSubregIndices(regs, numQubitsPerReg, numRegs, densShift);
- -
875  qureg, regs, numQubitsPerReg, numRegs,
-
876  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
877  NULL, NULL, 0,
-
878  conj);
-
879  shiftSubregIndices(regs, numQubitsPerReg, numRegs, - densShift);
-
880  }
- -
882  qureg, regs, numQubitsPerReg, numRegs,
-
883  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
884  NULL, NULL, 0);
-
885  }
-
886 
-
887  // final swaps
-
888  for (int i=0; i<(numQubits/2); i++) {
-
889 
-
890  int qb1 = qubits[i];
-
891  int qb2 = qubits[numQubits-i-1];
-
892 
-
893  statevec_swapQubitAmps(qureg, qb1, qb2);
-
894  if (qureg.isDensityMatrix)
-
895  statevec_swapQubitAmps(qureg, qb1 + densShift, qb2 + densShift);
-
896  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
-
897  }
-
898 }
-
-

References GATE_HADAMARD, GATE_SWAP, Qureg::isDensityMatrix, M_PI, Qureg::numQubitsRepresented, qasm_recordControlledGate(), qasm_recordGate(), qasm_recordNamedPhaseFunc(), qreal, SCALED_PRODUCT, shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_hadamard(), statevec_swapQubitAmps(), and UNSIGNED.

- -

Referenced by applyFullQFT(), and applyQFT().

+
865  // succession of C-phases, control on qubits[q], targeting each of
+
866  // qubits[q-1], qubits[q-1], ... qubits[0]. This can be expressed by
+
867  // a single invocation of applyNamedPhaseFunc product
+
868 
+
869  int numRegs = 2;
+
870  int numQubitsPerReg[2] = {q, 1};
+
871  int regs[100]; // [q+1];
+
872  for (int i=0; i<q+1; i++)
+
873  regs[i] = qubits[i]; // qubits[q] is in own register
+
874 
+
875  int numParams = 1;
+
876  qreal params[1] = { M_PI / (1 << q) };
+
877 
+
878  int conj = 0;
+ +
880  qureg, regs, numQubitsPerReg, numRegs,
+
881  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
882  NULL, NULL, 0,
+
883  conj);
+
884  if (qureg.isDensityMatrix) {
+
885  conj = 1;
+
886  shiftSubregIndices(regs, numQubitsPerReg, numRegs, densShift);
+ +
888  qureg, regs, numQubitsPerReg, numRegs,
+
889  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
890  NULL, NULL, 0,
+
891  conj);
+
892  shiftSubregIndices(regs, numQubitsPerReg, numRegs, - densShift);
+
893  }
+ +
895  qureg, regs, numQubitsPerReg, numRegs,
+
896  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
897  NULL, NULL, 0);
+
898  }
+
899 
+
900  // final swaps
+
901  for (int i=0; i<(numQubits/2); i++) {
+
902 
+
903  int qb1 = qubits[i];
+
904  int qb2 = qubits[numQubits-i-1];
+
905 
+
906  statevec_swapQubitAmps(qureg, qb1, qb2);
+
907  if (qureg.isDensityMatrix)
+
908  statevec_swapQubitAmps(qureg, qb1 + densShift, qb2 + densShift);
+
909  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
+
910  }
+
911 }
+
+

References GATE_HADAMARD, GATE_SWAP, Qureg::isDensityMatrix, M_PI, Qureg::numQubitsRepresented, qasm_recordControlledGate(), qasm_recordGate(), qasm_recordNamedPhaseFunc(), qreal, SCALED_PRODUCT, shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_hadamard(), statevec_swapQubitAmps(), and UNSIGNED.

+ +

Referenced by applyFullQFT(), and applyQFT().

@@ -588,19 +585,19 @@

-

Definition at line 827 of file QuEST_common.c.

-
827  {
-
828 
-
829  if (time == 0)
-
830  return;
-
831 
-
832  for (int r=0; r<reps; r++)
-
833  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
-
834 }
+

Definition at line 840 of file QuEST_common.c.

+
840  {
+
841 
+
842  if (time == 0)
+
843  return;
+
844 
+
845  for (int r=0; r<reps; r++)
+
846  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
+
847 }
-

References applySymmetrizedTrotterCircuit().

+

References applySymmetrizedTrotterCircuit().

-

Referenced by applyTrotterCircuit().

+

Referenced by applyTrotterCircuit().

@@ -642,65 +639,65 @@

-

Definition at line 752 of file QuEST_common.c.

-
752  {
-
753 
-
754  /* applies a first-order one-repetition approximation of exp(-i fac H)
-
755  * to qureg. Letting H = sum_j c_j h_j, it does this via
-
756  * exp(-i fac H) ~ prod_j exp(-i fac c_j h_j), where each inner exp
-
757  * is performed with multiRotatePauli (with pre-factor 2).
-
758  */
-
759 
-
760  // prepare targets for multiRotatePauli
-
761  // (all qubits; actual targets are determined by Pauli codes)
-
762  int vecTargs[hamil.numQubits];
-
763  int densTargs[hamil.numQubits];
-
764  for (int q=0; q<hamil.numQubits; q++) {
-
765  vecTargs[q] = q;
-
766  densTargs[q] = q + hamil.numQubits;
-
767  }
-
768 
-
769  for (int i=0; i<hamil.numSumTerms; i++) {
-
770 
-
771  int t=i;
-
772  if (reverse)
-
773  t=hamil.numSumTerms-1-i;
-
774 
-
775  qreal angle = 2*fac*hamil.termCoeffs[t];
-
776 
- -
778  qureg, vecTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
779  hamil.numQubits, angle, 0);
-
780 
-
781  if (qureg.isDensityMatrix)
- -
783  qureg, densTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
784  hamil.numQubits, angle, 1);
-
785 
-
786  // record qasm
-
787  char buff[1024];
-
788  int b=0;
-
789  for (int q=0; q<hamil.numQubits; q++) {
-
790  enum pauliOpType op = hamil.pauliCodes[q + t*hamil.numQubits];
-
791 
-
792  char p = 'I';
-
793  if (op == PAULI_X) p = 'X';
-
794  if (op == PAULI_Y) p = 'Y';
-
795  if (op == PAULI_Z) p = 'Z';
-
796  buff[b++] = p;
-
797  buff[b++] = ' ';
-
798  }
-
799  buff[b] = '\0';
-
800 
-
801  qasm_recordComment(qureg,
-
802  "Here, a multiRotatePauli with angle %g and paulis %s was applied.",
-
803  angle, buff);
-
804  }
-
805 }
-
-

References Qureg::isDensityMatrix, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qasm_recordComment(), qreal, statevec_multiRotatePauli(), and PauliHamil::termCoeffs.

- -

Referenced by applySymmetrizedTrotterCircuit().

+

Definition at line 765 of file QuEST_common.c.

+
765  {
+
766 
+
767  /* applies a first-order one-repetition approximation of exp(-i fac H)
+
768  * to qureg. Letting H = sum_j c_j h_j, it does this via
+
769  * exp(-i fac H) ~ prod_j exp(-i fac c_j h_j), where each inner exp
+
770  * is performed with multiRotatePauli (with pre-factor 2).
+
771  */
+
772 
+
773  // prepare targets for multiRotatePauli
+
774  // (all qubits; actual targets are determined by Pauli codes)
+
775  int vecTargs[100]; // [hamil.numQubits];
+
776  int densTargs[100]; // [hamil.numQubits];
+
777  for (int q=0; q<hamil.numQubits; q++) {
+
778  vecTargs[q] = q;
+
779  densTargs[q] = q + hamil.numQubits;
+
780  }
+
781 
+
782  for (int i=0; i<hamil.numSumTerms; i++) {
+
783 
+
784  int t=i;
+
785  if (reverse)
+
786  t=hamil.numSumTerms-1-i;
+
787 
+
788  qreal angle = 2*fac*hamil.termCoeffs[t];
+
789 
+ +
791  qureg, vecTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
+
792  hamil.numQubits, angle, 0);
+
793 
+
794  if (qureg.isDensityMatrix)
+ +
796  qureg, densTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
+
797  hamil.numQubits, angle, 1);
+
798 
+
799  // record qasm
+
800  char buff[1024];
+
801  int b=0;
+
802  for (int q=0; q<hamil.numQubits; q++) {
+
803  enum pauliOpType op = hamil.pauliCodes[q + t*hamil.numQubits];
+
804 
+
805  char p = 'I';
+
806  if (op == PAULI_X) p = 'X';
+
807  if (op == PAULI_Y) p = 'Y';
+
808  if (op == PAULI_Z) p = 'Z';
+
809  buff[b++] = p;
+
810  buff[b++] = ' ';
+
811  }
+
812  buff[b] = '\0';
+
813 
+
814  qasm_recordComment(qureg,
+
815  "Here, a multiRotatePauli with angle %g and paulis %s was applied.",
+
816  angle, buff);
+
817  }
+
818 }
+
+

References Qureg::isDensityMatrix, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qasm_recordComment(), qreal, statevec_multiRotatePauli(), and PauliHamil::termCoeffs.

+ +

Referenced by applySymmetrizedTrotterCircuit().

@@ -742,30 +739,30 @@

-

Definition at line 807 of file QuEST_common.c.

-
807  {
-
808 
-
809  if (order == 1) {
-
810  applyExponentiatedPauliHamil(qureg, hamil, time, 0);
-
811  }
-
812  else if (order == 2) {
-
813  applyExponentiatedPauliHamil(qureg, hamil, time/2., 0);
-
814  applyExponentiatedPauliHamil(qureg, hamil, time/2., 1);
-
815  }
-
816  else {
-
817  qreal p = 1. / (4 - pow(4, 1./(order-1)));
-
818  int lower = order-2;
-
819  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
820  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
821  applySymmetrizedTrotterCircuit(qureg, hamil, (1-4*p)*time, lower);
-
822  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
823  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+

Definition at line 820 of file QuEST_common.c.

+
820  {
+
821 
+
822  if (order == 1) {
+
823  applyExponentiatedPauliHamil(qureg, hamil, time, 0);
824  }
-
825 }
+
825  else if (order == 2) {
+
826  applyExponentiatedPauliHamil(qureg, hamil, time/2., 0);
+
827  applyExponentiatedPauliHamil(qureg, hamil, time/2., 1);
+
828  }
+
829  else {
+
830  qreal p = 1. / (4 - pow(4, 1./(order-1)));
+
831  int lower = order-2;
+
832  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
833  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
834  applySymmetrizedTrotterCircuit(qureg, hamil, (1-4*p)*time, lower);
+
835  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
836  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
837  }
+
838 }
-

References applyExponentiatedPauliHamil(), and qreal.

+

References applyExponentiatedPauliHamil(), and qreal.

-

Referenced by agnostic_applyTrotterCircuit().

+

Referenced by agnostic_applyTrotterCircuit().

@@ -813,20 +810,20 @@

-

Definition at line 661 of file QuEST_common.c.

-
664  {
-
665  ComplexMatrixN m;
-
666  m.numQubits = numQubits;
-
667  m.real = reStorage;
-
668  m.imag = imStorage;
-
669 
-
670  int len = 1<<numQubits;
-
671  for (int i=0; i<len; i++) {
-
672  m.real[i] = re[i];
-
673  m.imag[i] = im[i];
-
674  }
-
675  return m;
-
676 }
+

Definition at line 652 of file QuEST_common.c.

+
655  {
+
656  ComplexMatrixN m;
+
657  m.numQubits = numQubits;
+
658  m.real = reStorage;
+
659  m.imag = imStorage;
+
660 
+
661  int len = 1<<numQubits;
+
662  for (int i=0; i<len; i++) {
+
663  m.real[i] = re[i];
+
664  m.imag[i] = im[i];
+
665  }
+
666  return m;
+
667 }

References ComplexMatrixN::imag, ComplexMatrixN::numQubits, and ComplexMatrixN::real.

@@ -864,16 +861,16 @@

-

Definition at line 630 of file QuEST_common.c.

-
630  {
-
631 
-
632  long long int ctrlMask = 0;
-
633  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, target, target + qureg.numQubitsRepresented, superOp);
-
634 }
+

Definition at line 620 of file QuEST_common.c.

+
620  {
+
621 
+
622  long long int ctrlMask = 0;
+
623  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, target, target + qureg.numQubitsRepresented, superOp);
+
624 }
-

References Qureg::numQubitsRepresented, and statevec_multiControlledTwoQubitUnitary().

+

References Qureg::numQubitsRepresented, and statevec_multiControlledTwoQubitUnitary().

-

Referenced by densmatr_mixKrausMap().

+

Referenced by densmatr_mixKrausMap().

@@ -915,20 +912,20 @@

-

Definition at line 644 of file QuEST_common.c.

-
644  {
-
645  long long int ctrlMask = 0;
-
646  int allTargets[2*numTargets];
-
647  for (int t=0; t < numTargets; t++) {
-
648  allTargets[t] = targets[t];
-
649  allTargets[t+numTargets] = targets[t] + qureg.numQubitsRepresented;
-
650  }
-
651  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 2*numTargets, superOp);
-
652 }
+

Definition at line 634 of file QuEST_common.c.

+
634  {
+
635  long long int ctrlMask = 0;
+
636  int allTargets[200]; // [2*numTargets];
+
637  for (int t=0; t < numTargets; t++) {
+
638  allTargets[t] = targets[t];
+
639  allTargets[t+numTargets] = targets[t] + qureg.numQubitsRepresented;
+
640  }
+
641  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 2*numTargets, superOp);
+
642 }
-

References Qureg::numQubitsRepresented, and statevec_multiControlledMultiQubitUnitary().

+

References Qureg::numQubitsRepresented, and statevec_multiControlledMultiQubitUnitary().

-

Referenced by densmatr_mixMultiQubitKrausMap().

+

Referenced by densmatr_mixMultiQubitKrausMap().

@@ -970,18 +967,18 @@

-

Definition at line 636 of file QuEST_common.c.

-
636  {
-
637 
-
638  long long int ctrlMask = 0;
-
639  int numQb = qureg.numQubitsRepresented;
-
640  int allTargets[4] = {target1, target2, target1+numQb, target2+numQb};
-
641  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 4, superOp);
-
642 }
+

Definition at line 626 of file QuEST_common.c.

+
626  {
+
627 
+
628  long long int ctrlMask = 0;
+
629  int numQb = qureg.numQubitsRepresented;
+
630  int allTargets[4] = {target1, target2, target1+numQb, target2+numQb};
+
631  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 4, superOp);
+
632 }
-

References Qureg::numQubitsRepresented, and statevec_multiControlledMultiQubitUnitary().

+

References Qureg::numQubitsRepresented, and statevec_multiControlledMultiQubitUnitary().

-

Referenced by densmatr_mixTwoQubitKrausMap().

+

Referenced by densmatr_mixTwoQubitKrausMap().

@@ -1017,18 +1014,18 @@

-

Definition at line 382 of file QuEST_common.c.

-
382  {
-
383 
-
384  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
-
385  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
386  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
387  return outcome;
-
388 }
+

Definition at line 372 of file QuEST_common.c.

+
372  {
+
373 
+
374  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
+
375  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
+
376  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
+
377  return outcome;
+
378 }
-

References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), generateMeasurementOutcome(), and qreal.

+

References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), generateMeasurementOutcome(), and qreal.

-

Referenced by measure(), and measureWithStats().

+

Referenced by measure(), and measureWithStats().

@@ -1070,17 +1067,17 @@

-

Definition at line 654 of file QuEST_common.c.

-
654  {
-
655 
-
656  ComplexMatrix4 superOp;
-
657  populateKrausSuperOperator2(&superOp, ops, numOps);
-
658  densmatr_applyKrausSuperoperator(qureg, target, superOp);
-
659 }
+

Definition at line 644 of file QuEST_common.c.

+
644  {
+
645 
+
646  ComplexMatrix4 superOp;
+
647  populateKrausSuperOperator2(&superOp, ops, numOps);
+
648  densmatr_applyKrausSuperoperator(qureg, target, superOp);
+
649 }
-

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

+

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

-

Referenced by densmatr_mixPauli(), and mixKrausMap().

+

Referenced by densmatr_mixPauli(), and mixKrausMap().

@@ -1128,43 +1125,52 @@

-

Definition at line 697 of file QuEST_common.c.

-
697  {
-
698 
-
699  ComplexMatrixN superOp;
-
700 
-
701  /* superOp will contain 2^(4 numTargets) complex numbers.
-
702  * At double precision, superOp will cost additional memory:
-
703  * numTargs=1 -> 0.25 KiB
-
704  * numTargs=2 -> 4 KiB
-
705  * numTargs=3 -> 64 KiB
-
706  * numTargs=4 -> 1 MiB
-
707  * numTargs=5 -> 16 MiB.
-
708  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
-
709  * this costs at most double.
-
710  *
-
711  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
-
712  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
-
713  * for numTargets < 4, superOp will be kept in the stack, else in the heap
-
714  */
-
715 
-
716  if (numTargets < 4) {
-
717  // everything must live in 'if' since this macro declares local vars
-
718  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
-
719  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
720  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
721  }
-
722  else {
-
723  superOp = createComplexMatrixN(2*numTargets);
-
724  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
725  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
726  destroyComplexMatrixN(superOp);
-
727  }
-
728 }
-
-

References createComplexMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperatorN().

- -

Referenced by mixMultiQubitKrausMap().

+

Definition at line 701 of file QuEST_common.c.

+
701  {
+
702 
+
703  ComplexMatrixN superOp;
+
704 
+
705  /* superOp will contain 2^(4 numTargets) complex numbers.
+
706  * At double precision, superOp will cost additional memory:
+
707  * numTargs=1 -> 0.25 KiB
+
708  * numTargs=2 -> 4 KiB
+
709  * numTargs=3 -> 64 KiB
+
710  * numTargs=4 -> 1 MiB
+
711  * numTargs=5 -> 16 MiB.
+
712  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
+
713  * this costs at most double.
+
714  *
+
715  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
+
716  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
+
717  * for numTargets < 4, superOp will be kept in the stack, else in the heap
+
718  */
+
719 
+
720  // if NOT on Windows, allocate ComplexN on stack depending on size
+
721  #ifndef _WIN32
+
722  if (numTargets < 4) {
+
723  // everything must live in 'if' since this macro declares local vars
+
724  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
+
725  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
726  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
727  }
+
728  else {
+
729  superOp = createComplexMatrixN(2*numTargets);
+
730  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
731  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
732  destroyComplexMatrixN(superOp);
+
733  }
+
734  // on Windows, we must always create in heap
+
735  #else
+
736  superOp = createComplexMatrixN(2*numTargets);
+
737  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
738  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
739  destroyComplexMatrixN(superOp);
+
740  #endif
+
741 }
+
+

References createComplexMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperatorN().

+ +

Referenced by mixMultiQubitKrausMap().

@@ -1212,32 +1218,32 @@

-

Definition at line 730 of file QuEST_common.c.

-
730  {
-
731 
-
732  // convert pauli probabilities into Kraus map
-
733  const int numOps = 4;
-
734  ComplexMatrix2 ops[numOps];
-
735  for (int n=0; n < numOps; n++)
-
736  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
-
737 
-
738  qreal facs[4] = { // literal numOps=4 for valid initialisation
-
739  sqrt(1-(probX + probY + probZ)),
-
740  sqrt(probX),
-
741  sqrt(probY),
-
742  sqrt(probZ)
-
743  };
-
744  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
-
745  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
-
746  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
-
747  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
-
748 
-
749  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
-
750 }
+

Definition at line 743 of file QuEST_common.c.

+
743  {
+
744 
+
745  // convert pauli probabilities into Kraus map
+
746  const int numOps = 4;
+
747  ComplexMatrix2 ops[4]; // [numOps];
+
748  for (int n=0; n < numOps; n++)
+
749  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
+
750 
+
751  qreal facs[4] = { // literal numOps=4 for valid initialisation
+
752  sqrt(1-(probX + probY + probZ)),
+
753  sqrt(probX),
+
754  sqrt(probY),
+
755  sqrt(probZ)
+
756  };
+
757  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
+
758  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
+
759  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
+
760  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
+
761 
+
762  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
+
763 }
-

References densmatr_mixKrausMap(), ComplexMatrix2::imag, qreal, and ComplexMatrix2::real.

+

References densmatr_mixKrausMap(), ComplexMatrix2::imag, qreal, and ComplexMatrix2::real.

-

Referenced by mixPauli().

+

Referenced by mixPauli().

@@ -1285,18 +1291,29 @@

-

Definition at line 689 of file QuEST_common.c.

-
689  {
-
690 
-
691  ComplexMatrixN superOp;
-
692  macro_allocStackComplexMatrixN(superOp, 4);
-
693  populateKrausSuperOperator4(&superOp, ops, numOps);
-
694  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
-
695 }
+

Definition at line 682 of file QuEST_common.c.

+
682  {
+
683 
+
684  // if NOT on Windows, allocate ComplexN on stack
+
685  #ifndef _WIN32
+
686  ComplexMatrixN superOp;
+
687  macro_allocStackComplexMatrixN(superOp, 4);
+
688  populateKrausSuperOperator4(&superOp, ops, numOps);
+
689  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
+
690 
+
691  // but on Windows, we MUST allocated dynamically
+
692  #else
+ +
694  populateKrausSuperOperator4(&superOp, ops, numOps);
+
695  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
+
696  destroyComplexMatrixN(superOp);
+
697 
+
698  #endif
+
699 }
-

References densmatr_applyTwoQubitKrausSuperoperator(), macro_allocStackComplexMatrixN, and populateKrausSuperOperator4().

+

References createComplexMatrixN(), densmatr_applyTwoQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperator4().

-

Referenced by mixTwoQubitKrausMap().

+

Referenced by mixTwoQubitKrausMap().

@@ -1336,7 +1353,7 @@

76  }
77 }
-

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

+

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

@@ -1386,7 +1403,7 @@

References genrand_real1().

-

Referenced by densmatr_measureWithStats(), and statevec_measureWithStats().

+

Referenced by densmatr_measureWithStats(), and statevec_measureWithStats().

@@ -1501,7 +1518,7 @@

References getUnitVector(), Complex::imag, Complex::real, Vector::x, Vector::y, and Vector::z.

-

Referenced by qasm_recordAxisRotation(), qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

+

Referenced by qasm_recordAxisRotation(), qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

@@ -1530,7 +1547,7 @@

References macro_setConjugateMatrix.

-

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

+

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

@@ -1559,7 +1576,7 @@

References macro_setConjugateMatrix.

-

Referenced by controlledTwoQubitUnitary(), multiControlledTwoQubitUnitary(), and twoQubitUnitary().

+

Referenced by controlledTwoQubitUnitary(), multiControlledTwoQubitUnitary(), and twoQubitUnitary().

@@ -1590,7 +1607,7 @@

References Complex::imag, and Complex::real.

-

Referenced by compactUnitary(), and controlledCompactUnitary().

+

Referenced by compactUnitary(), and controlledCompactUnitary().

@@ -1637,7 +1654,7 @@

67  return mask;
68 }
-

Referenced by multiStateControlledUnitary().

+

Referenced by multiStateControlledUnitary().

@@ -1677,7 +1694,7 @@

56  return mask;
57 }
-

Referenced by applyMultiControlledMatrixN(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiRotateZ(), multiStateControlledUnitary(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiRotatePauli(), and validateMultiControlsMultiTargets().

+

Referenced by applyMultiControlledMatrixN(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiRotateZ(), multiStateControlledUnitary(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiRotatePauli(), and validateMultiControlsMultiTargets().

@@ -1722,7 +1739,7 @@

216 #endif
217 }
-

Referenced by seedQuESTDefault().

+

Referenced by seedQuESTDefault().

@@ -1780,7 +1797,7 @@

References Vector::x, Vector::y, and Vector::z.

-

Referenced by getUnitVector(), and validateVector().

+

Referenced by getUnitVector(), and validateVector().

@@ -1909,15 +1926,15 @@

-

Definition at line 617 of file QuEST_common.c.

-
617  {
-
618  int opDim = 2;
-
619  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
620 }
+

Definition at line 607 of file QuEST_common.c.

+
607  {
+
608  int opDim = 2;
+
609  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
610 }
-

References macro_populateKrausOperator.

+

References macro_populateKrausOperator.

-

Referenced by densmatr_mixKrausMap().

+

Referenced by densmatr_mixKrausMap().

@@ -1953,15 +1970,15 @@

-

Definition at line 621 of file QuEST_common.c.

-
621  {
-
622  int opDim = 4;
-
623  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
624 }
+

Definition at line 611 of file QuEST_common.c.

+
611  {
+
612  int opDim = 4;
+
613  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
614 }
-

References macro_populateKrausOperator.

+

References macro_populateKrausOperator.

-

Referenced by densmatr_mixTwoQubitKrausMap().

+

Referenced by densmatr_mixTwoQubitKrausMap().

@@ -1997,15 +2014,15 @@

-

Definition at line 625 of file QuEST_common.c.

-
625  {
-
626  int opDim = 1 << ops[0].numQubits;
-
627  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
628 }
+

Definition at line 615 of file QuEST_common.c.

+
615  {
+
616  int opDim = 1 << ops[0].numQubits;
+
617  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
618 }
-

References macro_populateKrausOperator, and ComplexMatrixN::numQubits.

+

References macro_populateKrausOperator, and ComplexMatrixN::numQubits.

-

Referenced by densmatr_mixMultiQubitKrausMap().

+

Referenced by densmatr_mixMultiQubitKrausMap().

@@ -2033,7 +2050,7 @@

References macro_setConjugateMatrix, and ComplexMatrixN::numQubits.

-

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

+

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

@@ -2075,7 +2092,7 @@

158  indices[j] += shift;
159 }
-

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiQubitUnitary(), and multiRotatePauli().

+

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiQubitUnitary(), and multiRotatePauli().

@@ -2125,7 +2142,7 @@

165  allInds[i++] += shift;
166 }
-

Referenced by agnostic_applyQFT(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by agnostic_applyQFT(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -2167,23 +2184,23 @@

-

Definition at line 505 of file QuEST_common.c.

-
505  {
-
506 
-
507  for (int i=0; i < numTargets; i++) {
-
508  // (pauliCodes[i] == PAULI_I) applies no operation
-
509  if (pauliCodes[i] == PAULI_X)
-
510  statevec_pauliX(workspace, targetQubits[i]);
-
511  if (pauliCodes[i] == PAULI_Y)
-
512  statevec_pauliY(workspace, targetQubits[i]);
-
513  if (pauliCodes[i] == PAULI_Z)
-
514  statevec_pauliZ(workspace, targetQubits[i]);
-
515  }
-
516 }
+

Definition at line 495 of file QuEST_common.c.

+
495  {
+
496 
+
497  for (int i=0; i < numTargets; i++) {
+
498  // (pauliCodes[i] == PAULI_I) applies no operation
+
499  if (pauliCodes[i] == PAULI_X)
+
500  statevec_pauliX(workspace, targetQubits[i]);
+
501  if (pauliCodes[i] == PAULI_Y)
+
502  statevec_pauliY(workspace, targetQubits[i]);
+
503  if (pauliCodes[i] == PAULI_Z)
+
504  statevec_pauliZ(workspace, targetQubits[i]);
+
505  }
+
506 }
-

References PAULI_X, PAULI_Y, PAULI_Z, statevec_pauliX(), statevec_pauliY(), and statevec_pauliZ().

+

References PAULI_X, PAULI_Y, PAULI_Z, statevec_pauliX(), statevec_pauliY(), and statevec_pauliZ().

-

Referenced by statevec_applyPauliSum(), and statevec_calcExpecPauliProd().

+

Referenced by statevec_applyPauliSum(), and statevec_calcExpecPauliProd().

@@ -2231,33 +2248,33 @@

-

Definition at line 548 of file QuEST_common.c.

-
548  {
-
549 
-
550  int numQb = inQureg.numQubitsRepresented;
-
551  int targs[numQb];
-
552  for (int q=0; q < numQb; q++)
-
553  targs[q] = q;
-
554 
-
555  statevec_initBlankState(outQureg);
-
556 
-
557  for (int t=0; t < numSumTerms; t++) {
-
558  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
-
559  Complex iden = (Complex) {.real=1, .imag=0};
-
560  Complex zero = (Complex) {.real=0, .imag=0};
-
561 
-
562  // outQureg += coef paulis(inQureg)
-
563  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
564  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
-
565 
-
566  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
-
567  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
568  }
-
569 }
+

Definition at line 538 of file QuEST_common.c.

+
538  {
+
539 
+
540  int numQb = inQureg.numQubitsRepresented;
+
541  int targs[100]; // [numQb];
+
542  for (int q=0; q < numQb; q++)
+
543  targs[q] = q;
+
544 
+
545  statevec_initBlankState(outQureg);
+
546 
+
547  for (int t=0; t < numSumTerms; t++) {
+
548  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
+
549  Complex iden = (Complex) {.real=1, .imag=0};
+
550  Complex zero = (Complex) {.real=0, .imag=0};
+
551 
+
552  // outQureg += coef paulis(inQureg)
+
553  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
+
554  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
+
555 
+
556  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
+
557  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
+
558  }
+
559 }
-

References Qureg::numQubitsRepresented, Complex::real, statevec_applyPauliProd(), statevec_initBlankState(), and statevec_setWeightedQureg().

+

References Qureg::numQubitsRepresented, Complex::real, statevec_applyPauliProd(), statevec_initBlankState(), and statevec_setWeightedQureg().

-

Referenced by applyPauliHamil(), and applyPauliSum().

+

Referenced by applyPauliHamil(), and applyPauliSum().

@@ -2305,25 +2322,25 @@

-

Definition at line 519 of file QuEST_common.c.

-
519  {
-
520 
-
521  statevec_cloneQureg(workspace, qureg);
-
522  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
-
523 
-
524  // compute the expected value
-
525  qreal value;
-
526  if (qureg.isDensityMatrix)
-
527  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
-
528  else
-
529  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
-
530 
-
531  return value;
-
532 }
+

Definition at line 509 of file QuEST_common.c.

+
509  {
+
510 
+
511  statevec_cloneQureg(workspace, qureg);
+
512  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
+
513 
+
514  // compute the expected value
+
515  qreal value;
+
516  if (qureg.isDensityMatrix)
+
517  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
+
518  else
+
519  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
+
520 
+
521  return value;
+
522 }
-

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, qreal, Complex::real, statevec_applyPauliProd(), statevec_calcInnerProduct(), and statevec_cloneQureg().

+

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, qreal, Complex::real, statevec_applyPauliProd(), statevec_calcInnerProduct(), and statevec_cloneQureg().

-

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

+

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

@@ -2371,24 +2388,24 @@

-

Definition at line 534 of file QuEST_common.c.

-
534  {
-
535 
-
536  int numQb = qureg.numQubitsRepresented;
-
537  int targs[numQb];
-
538  for (int q=0; q < numQb; q++)
-
539  targs[q] = q;
-
540 
-
541  qreal value = 0;
-
542  for (int t=0; t < numSumTerms; t++)
-
543  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
-
544 
-
545  return value;
-
546 }
+

Definition at line 524 of file QuEST_common.c.

+
524  {
+
525 
+
526  int numQb = qureg.numQubitsRepresented;
+
527  int targs[100]; // [numQb];
+
528  for (int q=0; q < numQb; q++)
+
529  targs[q] = q;
+
530 
+
531  qreal value = 0;
+
532  for (int t=0; t < numSumTerms; t++)
+
533  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
+
534 
+
535  return value;
+
536 }
-

References Qureg::numQubitsRepresented, qreal, and statevec_calcExpecPauliProd().

+

References Qureg::numQubitsRepresented, qreal, and statevec_calcExpecPauliProd().

-

Referenced by calcExpecPauliHamil(), and calcExpecPauliSum().

+

Referenced by calcExpecPauliHamil(), and calcExpecPauliSum().

@@ -2418,17 +2435,17 @@

-

Definition at line 390 of file QuEST_common.c.

-
390  {
-
391 
-
392  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
-
393  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
-
394  return innerProdMag;
-
395 }
+

Definition at line 380 of file QuEST_common.c.

+
380  {
+
381 
+
382  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
+
383  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
+
384  return innerProdMag;
+
385 }

References Complex::imag, qreal, Complex::real, and statevec_calcInnerProduct().

-

Referenced by calcFidelity().

+

Referenced by calcFidelity().

@@ -2476,16 +2493,16 @@

-

Definition at line 589 of file QuEST_common.c.

-
589  {
-
590 
-
591  long long int ctrlMask = 1LL << ctrl;
-
592  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
593 }
+

Definition at line 579 of file QuEST_common.c.

+
579  {
+
580 
+
581  long long int ctrlMask = 1LL << ctrl;
+
582  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
+
583 }
-

References statevec_multiControlledMultiQubitUnitary().

+

References statevec_multiControlledMultiQubitUnitary().

-

Referenced by controlledMultiQubitUnitary().

+

Referenced by controlledMultiQubitUnitary().

@@ -2533,17 +2550,17 @@

-

Definition at line 340 of file QuEST_common.c.

-
340  {
-
341 
-
342  Complex alpha, beta;
-
343  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
344  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
345 }
+

Definition at line 330 of file QuEST_common.c.

+
330  {
+
331 
+
332  Complex alpha, beta;
+
333  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
334  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
335 }
-

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

+

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

-

Referenced by controlledRotateAroundAxis(), statevec_controlledRotateX(), statevec_controlledRotateY(), and statevec_controlledRotateZ().

+

Referenced by controlledRotateAroundAxis(), statevec_controlledRotateX(), statevec_controlledRotateY(), and statevec_controlledRotateZ().

@@ -2591,19 +2608,19 @@

-

Definition at line 347 of file QuEST_common.c.

-
347  {
-
348 
-
349  Complex alpha, beta;
-
350  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
351  alpha.imag *= -1;
-
352  beta.imag *= -1;
-
353  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
354 }
+

Definition at line 337 of file QuEST_common.c.

+
337  {
+
338 
+
339  Complex alpha, beta;
+
340  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
341  alpha.imag *= -1;
+
342  beta.imag *= -1;
+
343  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
344 }
-

References getComplexPairFromRotation(), Complex::imag, and statevec_controlledCompactUnitary().

+

References getComplexPairFromRotation(), Complex::imag, and statevec_controlledCompactUnitary().

-

Referenced by controlledRotateAroundAxis().

+

Referenced by controlledRotateAroundAxis().

@@ -2645,16 +2662,16 @@

-

Definition at line 356 of file QuEST_common.c.

-
356  {
-
357 
-
358  Vector unitAxis = {1, 0, 0};
-
359  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
360 }
+

Definition at line 346 of file QuEST_common.c.

+
346  {
+
347 
+
348  Vector unitAxis = {1, 0, 0};
+
349  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
350 }
-

References statevec_controlledRotateAroundAxis().

+

References statevec_controlledRotateAroundAxis().

-

Referenced by controlledRotateX().

+

Referenced by controlledRotateX().

@@ -2696,16 +2713,16 @@

-

Definition at line 362 of file QuEST_common.c.

-
362  {
-
363 
-
364  Vector unitAxis = {0, 1, 0};
-
365  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
366 }
+

Definition at line 352 of file QuEST_common.c.

+
352  {
+
353 
+
354  Vector unitAxis = {0, 1, 0};
+
355  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
356 }
-

References statevec_controlledRotateAroundAxis().

+

References statevec_controlledRotateAroundAxis().

-

Referenced by controlledRotateY().

+

Referenced by controlledRotateY().

@@ -2747,16 +2764,16 @@

-

Definition at line 368 of file QuEST_common.c.

-
368  {
-
369 
-
370  Vector unitAxis = {0, 0, 1};
-
371  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
372 }
+

Definition at line 358 of file QuEST_common.c.

+
358  {
+
359 
+
360  Vector unitAxis = {0, 0, 1};
+
361  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
362 }
-

References statevec_controlledRotateAroundAxis().

+

References statevec_controlledRotateAroundAxis().

-

Referenced by controlledRotateZ().

+

Referenced by controlledRotateZ().

@@ -2804,16 +2821,16 @@

-

Definition at line 577 of file QuEST_common.c.

-
577  {
-
578 
-
579  long long int ctrlMask = 1LL << controlQubit;
-
580  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
581 }
+

Definition at line 567 of file QuEST_common.c.

+
567  {
+
568 
+
569  long long int ctrlMask = 1LL << controlQubit;
+
570  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
+
571 }
-

References statevec_multiControlledTwoQubitUnitary().

+

References statevec_multiControlledTwoQubitUnitary().

-

Referenced by controlledTwoQubitUnitary().

+

Referenced by controlledTwoQubitUnitary().

@@ -2843,16 +2860,16 @@

-

Definition at line 258 of file QuEST_common.c.

-
258  {
-
259  qreal real = statevec_getRealAmp(qureg, index);
-
260  qreal imag = statevec_getImagAmp(qureg, index);
-
261  return real*real + imag*imag;
-
262 }
+

Definition at line 248 of file QuEST_common.c.

+
248  {
+
249  qreal real = statevec_getRealAmp(qureg, index);
+
250  qreal imag = statevec_getImagAmp(qureg, index);
+
251  return real*real + imag*imag;
+
252 }
-

References qreal, statevec_getImagAmp(), and statevec_getRealAmp().

+

References qreal, statevec_getImagAmp(), and statevec_getRealAmp().

-

Referenced by getProbAmp().

+

Referenced by getProbAmp().

@@ -2888,18 +2905,18 @@

-

Definition at line 374 of file QuEST_common.c.

-
374  {
-
375 
-
376  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
-
377  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
378  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
379  return outcome;
-
380 }
+

Definition at line 364 of file QuEST_common.c.

+
364  {
+
365 
+
366  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
+
367  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
+
368  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
+
369  return outcome;
+
370 }
-

References generateMeasurementOutcome(), qreal, statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

+

References generateMeasurementOutcome(), qreal, statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

-

Referenced by measure(), and measureWithStats().

+

Referenced by measure(), and measureWithStats().

@@ -2959,48 +2976,48 @@

-

Definition at line 463 of file QuEST_common.c.

-
466  {
-
467  qreal fac = 1/sqrt(2);
-
468  qreal sgn = (applyConj)? 1 : -1;
-
469  ComplexMatrix2 uRx = {.real={{fac,0},{0,fac}}, .imag={{0,sgn*fac},{sgn*fac,0}}}; // Rx(pi/2)* rotates Z -> Y
-
470  ComplexMatrix2 uRy = {.real={{fac,fac},{-fac,fac}}, .imag={{0,0},{0,0}}}; // Ry(-pi/2) rotates Z -> X
-
471 
-
472  // this function is controlled on the all-one state, so no ctrl flips
-
473  long long int ctrlFlipMask = 0;
-
474 
-
475  // mask may be modified to remove superfluous Identity ops
-
476  long long int targMask = getQubitBitMask(targetQubits, numTargets);
-
477 
-
478  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
479  for (int t=0; t < numTargets; t++) {
-
480  if (targetPaulis[t] == PAULI_I)
-
481  targMask -= 1LL << targetQubits[t]; // remove target from mask
-
482  if (targetPaulis[t] == PAULI_X)
-
483  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
-
484  if (targetPaulis[t] == PAULI_Y)
-
485  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
-
486  // (targetPaulis[t] == 3) is Z basis
-
487  }
-
488 
-
489  // does nothing if there are no qubits to 'rotate'
-
490  if (targMask != 0)
-
491  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, (applyConj)? -angle : angle);
-
492 
-
493  // undo X and Y basis rotations
-
494  uRx.imag[0][1] *= -1; uRx.imag[1][0] *= -1;
-
495  uRy.real[0][1] *= -1; uRy.real[1][0] *= -1;
-
496  for (int t=0; t < numTargets; t++) {
-
497  if (targetPaulis[t] == PAULI_X)
-
498  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
-
499  if (targetPaulis[t] == PAULI_Y)
-
500  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
-
501  }
-
502 }
-
-

References getQubitBitMask(), ComplexMatrix2::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, ComplexMatrix2::real, statevec_multiControlledMultiRotateZ(), and statevec_multiControlledUnitary().

- -

Referenced by multiControlledMultiRotatePauli().

+

Definition at line 453 of file QuEST_common.c.

+
456  {
+
457  qreal fac = 1/sqrt(2);
+
458  qreal sgn = (applyConj)? 1 : -1;
+
459  ComplexMatrix2 uRx = {.real={{fac,0},{0,fac}}, .imag={{0,sgn*fac},{sgn*fac,0}}}; // Rx(pi/2)* rotates Z -> Y
+
460  ComplexMatrix2 uRy = {.real={{fac,fac},{-fac,fac}}, .imag={{0,0},{0,0}}}; // Ry(-pi/2) rotates Z -> X
+
461 
+
462  // this function is controlled on the all-one state, so no ctrl flips
+
463  long long int ctrlFlipMask = 0;
+
464 
+
465  // mask may be modified to remove superfluous Identity ops
+
466  long long int targMask = getQubitBitMask(targetQubits, numTargets);
+
467 
+
468  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
+
469  for (int t=0; t < numTargets; t++) {
+
470  if (targetPaulis[t] == PAULI_I)
+
471  targMask -= 1LL << targetQubits[t]; // remove target from mask
+
472  if (targetPaulis[t] == PAULI_X)
+
473  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
+
474  if (targetPaulis[t] == PAULI_Y)
+
475  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
+
476  // (targetPaulis[t] == 3) is Z basis
+
477  }
+
478 
+
479  // does nothing if there are no qubits to 'rotate'
+
480  if (targMask != 0)
+
481  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, (applyConj)? -angle : angle);
+
482 
+
483  // undo X and Y basis rotations
+
484  uRx.imag[0][1] *= -1; uRx.imag[1][0] *= -1;
+
485  uRy.real[0][1] *= -1; uRy.real[1][0] *= -1;
+
486  for (int t=0; t < numTargets; t++) {
+
487  if (targetPaulis[t] == PAULI_X)
+
488  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
+
489  if (targetPaulis[t] == PAULI_Y)
+
490  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
+
491  }
+
492 }
+
+

References getQubitBitMask(), ComplexMatrix2::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, ComplexMatrix2::real, statevec_multiControlledMultiRotateZ(), and statevec_multiControlledUnitary().

+ +

Referenced by multiControlledMultiRotatePauli().

@@ -3042,16 +3059,16 @@

-

Definition at line 583 of file QuEST_common.c.

-
583  {
-
584 
-
585  long long int ctrlMask = 0;
-
586  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
587 }
+

Definition at line 573 of file QuEST_common.c.

+
573  {
+
574 
+
575  long long int ctrlMask = 0;
+
576  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
+
577 }
-

References statevec_multiControlledMultiQubitUnitary().

+

References statevec_multiControlledMultiQubitUnitary().

-

Referenced by applyMatrixN(), and multiQubitUnitary().

+

Referenced by applyMatrixN(), and multiQubitUnitary().

@@ -3107,46 +3124,46 @@

Definition at line 424 of file QuEST_common.c.

-
427  {
-
428  qreal fac = 1/sqrt(2);
-
429  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
-
430  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
-
431  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
-
432  Complex uRyBeta = {.real = -fac, .imag = 0};
-
433 
-
434  // mask may be modified to remove superfluous Identity ops
-
435  long long int mask = getQubitBitMask(targetQubits, numTargets);
-
436 
-
437  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
438  for (int t=0; t < numTargets; t++) {
-
439  if (targetPaulis[t] == PAULI_I)
-
440  mask -= 1LL << targetQubits[t]; // remove target from mask
-
441  if (targetPaulis[t] == PAULI_X)
-
442  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
443  if (targetPaulis[t] == PAULI_Y)
-
444  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
445  // (targetPaulis[t] == 3) is Z basis
-
446  }
-
447 
-
448  // does nothing if there are no qubits to 'rotate'
-
449  if (mask != 0)
-
450  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
-
451 
-
452  // undo X and Y basis rotations
-
453  uRxBeta.imag *= -1;
-
454  uRyBeta.real *= -1;
-
455  for (int t=0; t < numTargets; t++) {
-
456  if (targetPaulis[t] == PAULI_X)
-
457  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
458  if (targetPaulis[t] == PAULI_Y)
-
459  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
460  }
-
461 }
-
-

References getQubitBitMask(), Complex::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, Complex::real, statevec_compactUnitary(), and statevec_multiRotateZ().

- -

Referenced by applyExponentiatedPauliHamil(), and multiRotatePauli().

+

Definition at line 414 of file QuEST_common.c.

+
417  {
+
418  qreal fac = 1/sqrt(2);
+
419  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
+
420  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
+
421  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
+
422  Complex uRyBeta = {.real = -fac, .imag = 0};
+
423 
+
424  // mask may be modified to remove superfluous Identity ops
+
425  long long int mask = getQubitBitMask(targetQubits, numTargets);
+
426 
+
427  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
+
428  for (int t=0; t < numTargets; t++) {
+
429  if (targetPaulis[t] == PAULI_I)
+
430  mask -= 1LL << targetQubits[t]; // remove target from mask
+
431  if (targetPaulis[t] == PAULI_X)
+
432  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
+
433  if (targetPaulis[t] == PAULI_Y)
+
434  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
+
435  // (targetPaulis[t] == 3) is Z basis
+
436  }
+
437 
+
438  // does nothing if there are no qubits to 'rotate'
+
439  if (mask != 0)
+
440  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
+
441 
+
442  // undo X and Y basis rotations
+
443  uRxBeta.imag *= -1;
+
444  uRyBeta.real *= -1;
+
445  for (int t=0; t < numTargets; t++) {
+
446  if (targetPaulis[t] == PAULI_X)
+
447  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
+
448  if (targetPaulis[t] == PAULI_Y)
+
449  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
+
450  }
+
451 }
+
+

References getQubitBitMask(), Complex::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, Complex::real, statevec_compactUnitary(), and statevec_multiRotateZ().

+ +

Referenced by applyExponentiatedPauliHamil(), and multiRotatePauli().

@@ -3176,17 +3193,17 @@

-

Definition at line 271 of file QuEST_common.c.

-
271  {
-
272  Complex term;
-
273  term.real = -1;
-
274  term.imag = 0;
-
275  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
276 }
+

Definition at line 261 of file QuEST_common.c.

+
261  {
+
262  Complex term;
+
263  term.real = -1;
+
264  term.imag = 0;
+
265  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
266 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by pauliZ(), and statevec_applyPauliProd().

+

Referenced by pauliZ(), and statevec_applyPauliProd().

@@ -3222,17 +3239,17 @@

-

Definition at line 264 of file QuEST_common.c.

-
264  {
-
265  Complex term;
-
266  term.real = cos(angle);
-
267  term.imag = sin(angle);
-
268  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
269 }
+

Definition at line 254 of file QuEST_common.c.

+
254  {
+
255  Complex term;
+
256  term.real = cos(angle);
+
257  term.imag = sin(angle);
+
258  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
259 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by phaseShift().

+

Referenced by phaseShift().

@@ -3274,17 +3291,17 @@

-

Definition at line 324 of file QuEST_common.c.

-
324  {
-
325 
-
326  Complex alpha, beta;
-
327  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
328  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
329 }
+

Definition at line 314 of file QuEST_common.c.

+
314  {
+
315 
+
316  Complex alpha, beta;
+
317  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
318  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
+
319 }
-

References getComplexPairFromRotation(), and statevec_compactUnitary().

+

References getComplexPairFromRotation(), and statevec_compactUnitary().

-

Referenced by rotateAroundAxis(), statevec_rotateX(), statevec_rotateY(), and statevec_rotateZ().

+

Referenced by rotateAroundAxis(), statevec_rotateX(), statevec_rotateY(), and statevec_rotateZ().

@@ -3326,19 +3343,19 @@

-

Definition at line 331 of file QuEST_common.c.

-
331  {
-
332 
-
333  Complex alpha, beta;
-
334  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
335  alpha.imag *= -1;
-
336  beta.imag *= -1;
-
337  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
338 }
+

Definition at line 321 of file QuEST_common.c.

+
321  {
+
322 
+
323  Complex alpha, beta;
+
324  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
325  alpha.imag *= -1;
+
326  beta.imag *= -1;
+
327  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
+
328 }
-

References getComplexPairFromRotation(), Complex::imag, and statevec_compactUnitary().

+

References getComplexPairFromRotation(), Complex::imag, and statevec_compactUnitary().

-

Referenced by rotateAroundAxis().

+

Referenced by rotateAroundAxis().

@@ -3374,16 +3391,16 @@

-

Definition at line 306 of file QuEST_common.c.

-
306  {
-
307 
-
308  Vector unitAxis = {1, 0, 0};
-
309  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
310 }
+

Definition at line 296 of file QuEST_common.c.

+
296  {
+
297 
+
298  Vector unitAxis = {1, 0, 0};
+
299  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
300 }
-

References statevec_rotateAroundAxis().

+

References statevec_rotateAroundAxis().

-

Referenced by rotateX().

+

Referenced by rotateX().

@@ -3419,16 +3436,16 @@

-

Definition at line 312 of file QuEST_common.c.

-
312  {
-
313 
-
314  Vector unitAxis = {0, 1, 0};
-
315  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
316 }
+

Definition at line 302 of file QuEST_common.c.

+
302  {
+
303 
+
304  Vector unitAxis = {0, 1, 0};
+
305  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
306 }
-

References statevec_rotateAroundAxis().

+

References statevec_rotateAroundAxis().

-

Referenced by rotateY().

+

Referenced by rotateY().

@@ -3464,16 +3481,16 @@

-

Definition at line 318 of file QuEST_common.c.

-
318  {
-
319 
-
320  Vector unitAxis = {0, 0, 1};
-
321  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
322 }
+

Definition at line 308 of file QuEST_common.c.

+
308  {
+
309 
+
310  Vector unitAxis = {0, 0, 1};
+
311  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
312 }
-

References statevec_rotateAroundAxis().

+

References statevec_rotateAroundAxis().

-

Referenced by rotateZ().

+

Referenced by rotateZ().

@@ -3503,17 +3520,17 @@

-

Definition at line 278 of file QuEST_common.c.

-
278  {
-
279  Complex term;
-
280  term.real = 0;
-
281  term.imag = 1;
-
282  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
283 }
+

Definition at line 268 of file QuEST_common.c.

+
268  {
+
269  Complex term;
+
270  term.real = 0;
+
271  term.imag = 1;
+
272  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
273 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by sGate().

+

Referenced by sGate().

@@ -3543,17 +3560,17 @@

-

Definition at line 292 of file QuEST_common.c.

-
292  {
-
293  Complex term;
-
294  term.real = 0;
-
295  term.imag = -1;
-
296  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
297 }
+

Definition at line 282 of file QuEST_common.c.

+
282  {
+
283  Complex term;
+
284  term.real = 0;
+
285  term.imag = -1;
+
286  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
287 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by sGate().

+

Referenced by sGate().

@@ -3589,23 +3606,23 @@

-

Definition at line 397 of file QuEST_common.c.

-
397  {
-
398 
-
399  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
400  u.real[0][0]=1;
-
401  u.real[3][3]=1;
-
402  u.real[1][1] = .5; u.imag[1][1] = .5;
-
403  u.real[1][2] = .5; u.imag[1][2] =-.5;
-
404  u.real[2][1] = .5; u.imag[2][1] =-.5;
-
405  u.real[2][2] = .5; u.imag[2][2] = .5;
-
406 
-
407  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
408 }
+

Definition at line 387 of file QuEST_common.c.

+
387  {
+
388 
+
389  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
+
390  u.real[0][0]=1;
+
391  u.real[3][3]=1;
+
392  u.real[1][1] = .5; u.imag[1][1] = .5;
+
393  u.real[1][2] = .5; u.imag[1][2] =-.5;
+
394  u.real[2][1] = .5; u.imag[2][1] =-.5;
+
395  u.real[2][2] = .5; u.imag[2][2] = .5;
+
396 
+
397  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
+
398 }
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

+

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

-

Referenced by sqrtSwapGate().

+

Referenced by sqrtSwapGate().

@@ -3641,23 +3658,23 @@

-

Definition at line 410 of file QuEST_common.c.

-
410  {
-
411 
-
412  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
413  u.real[0][0]=1;
-
414  u.real[3][3]=1;
-
415  u.real[1][1] = .5; u.imag[1][1] =-.5;
-
416  u.real[1][2] = .5; u.imag[1][2] = .5;
-
417  u.real[2][1] = .5; u.imag[2][1] = .5;
-
418  u.real[2][2] = .5; u.imag[2][2] =-.5;
-
419 
-
420  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
421 }
+

Definition at line 400 of file QuEST_common.c.

+
400  {
+
401 
+
402  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
+
403  u.real[0][0]=1;
+
404  u.real[3][3]=1;
+
405  u.real[1][1] = .5; u.imag[1][1] =-.5;
+
406  u.real[1][2] = .5; u.imag[1][2] = .5;
+
407  u.real[2][1] = .5; u.imag[2][1] = .5;
+
408  u.real[2][2] = .5; u.imag[2][2] =-.5;
+
409 
+
410  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
+
411 }
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

+

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

-

Referenced by sqrtSwapGate().

+

Referenced by sqrtSwapGate().

@@ -3687,17 +3704,17 @@

-

Definition at line 285 of file QuEST_common.c.

-
285  {
-
286  Complex term;
-
287  term.real = 1/sqrt(2);
-
288  term.imag = 1/sqrt(2);
-
289  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
290 }
+

Definition at line 275 of file QuEST_common.c.

+
275  {
+
276  Complex term;
+
277  term.real = 1/sqrt(2);
+
278  term.imag = 1/sqrt(2);
+
279  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
280 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by tGate().

+

Referenced by tGate().

@@ -3727,17 +3744,17 @@

-

Definition at line 299 of file QuEST_common.c.

-
299  {
-
300  Complex term;
-
301  term.real = 1/sqrt(2);
-
302  term.imag = -1/sqrt(2);
-
303  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
304 }
+

Definition at line 289 of file QuEST_common.c.

+
289  {
+
290  Complex term;
+
291  term.real = 1/sqrt(2);
+
292  term.imag = -1/sqrt(2);
+
293  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
294 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by tGate().

+

Referenced by tGate().

@@ -3779,110 +3796,110 @@

-

Definition at line 571 of file QuEST_common.c.

-
571  {
-
572 
-
573  long long int ctrlMask = 0;
-
574  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
575 }
+

Definition at line 561 of file QuEST_common.c.

+
561  {
+
562 
+
563  long long int ctrlMask = 0;
+
564  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
+
565 }
-

References statevec_multiControlledTwoQubitUnitary().

+

References statevec_multiControlledTwoQubitUnitary().

-

Referenced by applyMatrix4(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and twoQubitUnitary().

+

Referenced by applyMatrix4(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and twoQubitUnitary().

Represents a 3-vector of real numbers.
Definition: QuEST.h:198
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:271
+
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:261
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:99
qreal real[4][4]
Definition: QuEST.h:177
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:654
+
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:644
@ PAULI_Z
Definition: QuEST.h:96
-
void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
Definition: QuEST_common.c:752
-
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:621
-
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:625
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1356
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:519
+
void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
Definition: QuEST_common.c:765
+
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:611
+
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:615
+
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1369
+
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:509
@ PAULI_I
Definition: QuEST.h:96
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1335
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:571
+
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1348
+
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:561
qreal z
Definition: QuEST.h:200
-
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:505
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3277
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:495
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3316
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
Vector getUnitVector(Vector vec)
Definition: QuEST_common.c:84
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ UNSIGNED
Definition: QuEST.h:269
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:120
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:661
+
void statevec_pauliY(Qureg qureg, int targetQubit)
+
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:652
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
#define qreal
-
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:683
+
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:675
@ PAULI_X
Definition: QuEST.h:96
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
qreal densmatr_calcTotalProb(Qureg qureg)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:239
qreal y
Definition: QuEST.h:200
qreal imag[2][2]
Definition: QuEST.h:140
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4406
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3319
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3358
qreal x
Definition: QuEST.h:200
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:168
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:630
+
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:620
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
-
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:617
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
+
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:607
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1561
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:324
+
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1572
+
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:314
qreal imag[4][4]
Definition: QuEST.h:178
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
@ PAULI_Y
Definition: QuEST.h:96
double genrand_real1(void)
Definition: mt19937ar.c:150
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:424
+
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:414
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
qreal ** real
Definition: QuEST.h:189
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:340
+
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:330
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3965
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:4005
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
Definition: QuEST_common.c:161
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
qreal ** imag
Definition: QuEST.h:190
qreal real[2][2]
Definition: QuEST.h:139
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void statevec_hadamard(Qureg qureg, int targetQubit)
int numQubits
Definition: QuEST.h:188
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
-
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:636
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3146
+
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:626
+
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3185
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
-
void statevec_pauliX(Qureg qureg, int targetQubit)
+
void statevec_pauliX(Qureg qureg, int targetQubit)
@ GATE_SWAP
Definition: QuEST_qasm.h:33
qreal real
Definition: QuEST.h:105
-
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:644
+
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:634
qreal imag
Definition: QuEST.h:106
Represents one complex number.
Definition: QuEST.h:103
-
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
Definition: QuEST_common.c:595
+
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
Definition: QuEST_common.c:585
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:179
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
#define M_PI
Definition: QuEST_common.c:41
-
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:807
+
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:820
void qasm_recordNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc funcName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:726
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
diff --git a/docs/QuEST__common_8c_source.html b/docs/QuEST__common_8c_source.html index 9d033cf43..7207be56b 100644 --- a/docs/QuEST__common_8c_source.html +++ b/docs/QuEST__common_8c_source.html @@ -27,7 +27,7 @@ @@ -259,725 +259,739 @@
216 #endif
217 }
218 
-
222 void seedQuEST(unsigned long int *seedArray, int numSeeds){
-
223  // init MT random number generator with user defined list of seeds
-
224  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
225  // used by the master process
-
226  init_by_array(seedArray, numSeeds);
-
227 }
-
228 
-
229 void reportState(Qureg qureg){
-
230  FILE *state;
-
231  char filename[100];
-
232  long long int index;
-
233  sprintf(filename, "state_rank_%d.csv", qureg.chunkId);
-
234  state = fopen(filename, "w");
-
235  if (qureg.chunkId==0) fprintf(state, "real, imag\n");
+
219 void reportState(Qureg qureg){
+
220  FILE *state;
+
221  char filename[100];
+
222  long long int index;
+
223  sprintf(filename, "state_rank_%d.csv", qureg.chunkId);
+
224  state = fopen(filename, "w");
+
225  if (qureg.chunkId==0) fprintf(state, "real, imag\n");
+
226 
+
227  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
228  # if QuEST_PREC==1 || QuEST_PREC==2
+
229  fprintf(state, "%.12f, %.12f\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
230  # elif QuEST_PREC == 4
+
231  fprintf(state, "%.12Lf, %.12Lf\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
232  #endif
+
233  }
+
234  fclose(state);
+
235 }
236 
-
237  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
238  # if QuEST_PREC==1 || QuEST_PREC==2
-
239  fprintf(state, "%.12f, %.12f\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
240  # elif QuEST_PREC == 4
-
241  fprintf(state, "%.12Lf, %.12Lf\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
242  #endif
-
243  }
-
244  fclose(state);
-
245 }
-
246 
- -
248  long long int numAmps = 1LL << qureg.numQubitsInStateVec;
-
249  long long int numAmpsPerRank = numAmps/qureg.numChunks;
-
250  if (qureg.chunkId==0){
-
251  printf("QUBITS:\n");
-
252  printf("Number of qubits is %d.\n", qureg.numQubitsInStateVec);
-
253  printf("Number of amps is %lld.\n", numAmps);
-
254  printf("Number of amps per rank is %lld.\n", numAmpsPerRank);
-
255  }
-
256 }
-
257 
-
258 qreal statevec_getProbAmp(Qureg qureg, long long int index){
-
259  qreal real = statevec_getRealAmp(qureg, index);
-
260  qreal imag = statevec_getImagAmp(qureg, index);
-
261  return real*real + imag*imag;
-
262 }
-
263 
-
264 void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle) {
-
265  Complex term;
-
266  term.real = cos(angle);
-
267  term.imag = sin(angle);
-
268  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
269 }
-
270 
-
271 void statevec_pauliZ(Qureg qureg, int targetQubit) {
-
272  Complex term;
-
273  term.real = -1;
-
274  term.imag = 0;
-
275  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
276 }
-
277 
-
278 void statevec_sGate(Qureg qureg, int targetQubit) {
-
279  Complex term;
-
280  term.real = 0;
-
281  term.imag = 1;
-
282  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
283 }
-
284 
-
285 void statevec_tGate(Qureg qureg, int targetQubit) {
-
286  Complex term;
-
287  term.real = 1/sqrt(2);
-
288  term.imag = 1/sqrt(2);
-
289  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
290 }
-
291 
-
292 void statevec_sGateConj(Qureg qureg, int targetQubit) {
-
293  Complex term;
-
294  term.real = 0;
-
295  term.imag = -1;
-
296  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
297 }
-
298 
-
299 void statevec_tGateConj(Qureg qureg, int targetQubit) {
-
300  Complex term;
-
301  term.real = 1/sqrt(2);
-
302  term.imag = -1/sqrt(2);
-
303  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
304 }
-
305 
-
306 void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle){
+ +
238  long long int numAmps = 1LL << qureg.numQubitsInStateVec;
+
239  long long int numAmpsPerRank = numAmps/qureg.numChunks;
+
240  if (qureg.chunkId==0){
+
241  printf("QUBITS:\n");
+
242  printf("Number of qubits is %d.\n", qureg.numQubitsInStateVec);
+
243  printf("Number of amps is %lld.\n", numAmps);
+
244  printf("Number of amps per rank is %lld.\n", numAmpsPerRank);
+
245  }
+
246 }
+
247 
+
248 qreal statevec_getProbAmp(Qureg qureg, long long int index){
+
249  qreal real = statevec_getRealAmp(qureg, index);
+
250  qreal imag = statevec_getImagAmp(qureg, index);
+
251  return real*real + imag*imag;
+
252 }
+
253 
+
254 void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle) {
+
255  Complex term;
+
256  term.real = cos(angle);
+
257  term.imag = sin(angle);
+
258  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
259 }
+
260 
+
261 void statevec_pauliZ(Qureg qureg, int targetQubit) {
+
262  Complex term;
+
263  term.real = -1;
+
264  term.imag = 0;
+
265  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
266 }
+
267 
+
268 void statevec_sGate(Qureg qureg, int targetQubit) {
+
269  Complex term;
+
270  term.real = 0;
+
271  term.imag = 1;
+
272  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
273 }
+
274 
+
275 void statevec_tGate(Qureg qureg, int targetQubit) {
+
276  Complex term;
+
277  term.real = 1/sqrt(2);
+
278  term.imag = 1/sqrt(2);
+
279  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
280 }
+
281 
+
282 void statevec_sGateConj(Qureg qureg, int targetQubit) {
+
283  Complex term;
+
284  term.real = 0;
+
285  term.imag = -1;
+
286  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
287 }
+
288 
+
289 void statevec_tGateConj(Qureg qureg, int targetQubit) {
+
290  Complex term;
+
291  term.real = 1/sqrt(2);
+
292  term.imag = -1/sqrt(2);
+
293  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
294 }
+
295 
+
296 void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle){
+
297 
+
298  Vector unitAxis = {1, 0, 0};
+
299  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
300 }
+
301 
+
302 void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle){
+
303 
+
304  Vector unitAxis = {0, 1, 0};
+
305  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
306 }
307 
-
308  Vector unitAxis = {1, 0, 0};
-
309  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
310 }
-
311 
-
312 void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle){
+
308 void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle){
+
309 
+
310  Vector unitAxis = {0, 0, 1};
+
311  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
312 }
313 
-
314  Vector unitAxis = {0, 1, 0};
-
315  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
316 }
-
317 
-
318 void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle){
-
319 
-
320  Vector unitAxis = {0, 0, 1};
-
321  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
322 }
-
323 
-
324 void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis){
-
325 
-
326  Complex alpha, beta;
-
327  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
328  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
329 }
-
330 
-
331 void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis){
-
332 
-
333  Complex alpha, beta;
-
334  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
335  alpha.imag *= -1;
-
336  beta.imag *= -1;
-
337  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
338 }
-
339 
-
340 void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis){
-
341 
-
342  Complex alpha, beta;
-
343  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
344  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
345 }
-
346 
-
347 void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis){
-
348 
-
349  Complex alpha, beta;
-
350  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
351  alpha.imag *= -1;
-
352  beta.imag *= -1;
-
353  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
354 }
-
355 
-
356 void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
+
314 void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis){
+
315 
+
316  Complex alpha, beta;
+
317  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
318  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
+
319 }
+
320 
+
321 void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis){
+
322 
+
323  Complex alpha, beta;
+
324  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
325  alpha.imag *= -1;
+
326  beta.imag *= -1;
+
327  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
+
328 }
+
329 
+
330 void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis){
+
331 
+
332  Complex alpha, beta;
+
333  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
334  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
335 }
+
336 
+
337 void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis){
+
338 
+
339  Complex alpha, beta;
+
340  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
341  alpha.imag *= -1;
+
342  beta.imag *= -1;
+
343  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
344 }
+
345 
+
346 void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
+
347 
+
348  Vector unitAxis = {1, 0, 0};
+
349  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
350 }
+
351 
+
352 void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
+
353 
+
354  Vector unitAxis = {0, 1, 0};
+
355  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
356 }
357 
-
358  Vector unitAxis = {1, 0, 0};
-
359  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
360 }
-
361 
-
362 void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
+
358 void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
+
359 
+
360  Vector unitAxis = {0, 0, 1};
+
361  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
362 }
363 
-
364  Vector unitAxis = {0, 1, 0};
-
365  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
366 }
-
367 
-
368 void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle){
-
369 
-
370  Vector unitAxis = {0, 0, 1};
-
371  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
372 }
-
373 
-
374 int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
-
375 
-
376  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
-
377  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
378  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
379  return outcome;
-
380 }
-
381 
-
382 int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
-
383 
-
384  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
-
385  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
386  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
387  return outcome;
-
388 }
-
389 
- -
391 
-
392  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
-
393  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
-
394  return innerProdMag;
-
395 }
-
396 
-
397 void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2) {
-
398 
-
399  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
400  u.real[0][0]=1;
-
401  u.real[3][3]=1;
-
402  u.real[1][1] = .5; u.imag[1][1] = .5;
-
403  u.real[1][2] = .5; u.imag[1][2] =-.5;
-
404  u.real[2][1] = .5; u.imag[2][1] =-.5;
-
405  u.real[2][2] = .5; u.imag[2][2] = .5;
-
406 
-
407  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
408 }
-
409 
-
410 void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2) {
-
411 
-
412  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
413  u.real[0][0]=1;
-
414  u.real[3][3]=1;
-
415  u.real[1][1] = .5; u.imag[1][1] =-.5;
-
416  u.real[1][2] = .5; u.imag[1][2] = .5;
-
417  u.real[2][1] = .5; u.imag[2][1] = .5;
-
418  u.real[2][2] = .5; u.imag[2][2] =-.5;
-
419 
-
420  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
421 }
-
422 
- -
425  Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle,
-
426  int applyConj
-
427 ) {
-
428  qreal fac = 1/sqrt(2);
-
429  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
-
430  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
-
431  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
-
432  Complex uRyBeta = {.real = -fac, .imag = 0};
-
433 
-
434  // mask may be modified to remove superfluous Identity ops
-
435  long long int mask = getQubitBitMask(targetQubits, numTargets);
-
436 
-
437  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
438  for (int t=0; t < numTargets; t++) {
-
439  if (targetPaulis[t] == PAULI_I)
-
440  mask -= 1LL << targetQubits[t]; // remove target from mask
-
441  if (targetPaulis[t] == PAULI_X)
-
442  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
443  if (targetPaulis[t] == PAULI_Y)
-
444  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
445  // (targetPaulis[t] == 3) is Z basis
-
446  }
-
447 
-
448  // does nothing if there are no qubits to 'rotate'
-
449  if (mask != 0)
-
450  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
-
451 
-
452  // undo X and Y basis rotations
-
453  uRxBeta.imag *= -1;
-
454  uRyBeta.real *= -1;
-
455  for (int t=0; t < numTargets; t++) {
-
456  if (targetPaulis[t] == PAULI_X)
-
457  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
458  if (targetPaulis[t] == PAULI_Y)
-
459  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
460  }
-
461 }
-
462 
- -
464  Qureg qureg, long long int ctrlMask, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle,
-
465  int applyConj
-
466 ) {
-
467  qreal fac = 1/sqrt(2);
-
468  qreal sgn = (applyConj)? 1 : -1;
-
469  ComplexMatrix2 uRx = {.real={{fac,0},{0,fac}}, .imag={{0,sgn*fac},{sgn*fac,0}}}; // Rx(pi/2)* rotates Z -> Y
-
470  ComplexMatrix2 uRy = {.real={{fac,fac},{-fac,fac}}, .imag={{0,0},{0,0}}}; // Ry(-pi/2) rotates Z -> X
-
471 
-
472  // this function is controlled on the all-one state, so no ctrl flips
-
473  long long int ctrlFlipMask = 0;
-
474 
-
475  // mask may be modified to remove superfluous Identity ops
-
476  long long int targMask = getQubitBitMask(targetQubits, numTargets);
-
477 
-
478  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
479  for (int t=0; t < numTargets; t++) {
-
480  if (targetPaulis[t] == PAULI_I)
-
481  targMask -= 1LL << targetQubits[t]; // remove target from mask
-
482  if (targetPaulis[t] == PAULI_X)
-
483  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
-
484  if (targetPaulis[t] == PAULI_Y)
-
485  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
-
486  // (targetPaulis[t] == 3) is Z basis
-
487  }
-
488 
-
489  // does nothing if there are no qubits to 'rotate'
-
490  if (targMask != 0)
-
491  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, (applyConj)? -angle : angle);
-
492 
-
493  // undo X and Y basis rotations
-
494  uRx.imag[0][1] *= -1; uRx.imag[1][0] *= -1;
-
495  uRy.real[0][1] *= -1; uRy.real[1][0] *= -1;
-
496  for (int t=0; t < numTargets; t++) {
-
497  if (targetPaulis[t] == PAULI_X)
-
498  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
-
499  if (targetPaulis[t] == PAULI_Y)
-
500  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
-
501  }
-
502 }
-
503 
-
504 /* produces both pauli|qureg> or pauli * qureg (as a density matrix) */
-
505 void statevec_applyPauliProd(Qureg workspace, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets) {
-
506 
-
507  for (int i=0; i < numTargets; i++) {
-
508  // (pauliCodes[i] == PAULI_I) applies no operation
-
509  if (pauliCodes[i] == PAULI_X)
-
510  statevec_pauliX(workspace, targetQubits[i]);
-
511  if (pauliCodes[i] == PAULI_Y)
-
512  statevec_pauliY(workspace, targetQubits[i]);
-
513  if (pauliCodes[i] == PAULI_Z)
-
514  statevec_pauliZ(workspace, targetQubits[i]);
-
515  }
-
516 }
-
517 
-
518 // <pauli> = <qureg|pauli|qureg> = qureg . pauli(qureg)
-
519 qreal statevec_calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace) {
-
520 
-
521  statevec_cloneQureg(workspace, qureg);
-
522  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
-
523 
-
524  // compute the expected value
-
525  qreal value;
-
526  if (qureg.isDensityMatrix)
-
527  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
-
528  else
-
529  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
-
530 
-
531  return value;
-
532 }
-
533 
-
534 qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace) {
-
535 
-
536  int numQb = qureg.numQubitsRepresented;
-
537  int targs[numQb];
-
538  for (int q=0; q < numQb; q++)
-
539  targs[q] = q;
-
540 
-
541  qreal value = 0;
-
542  for (int t=0; t < numSumTerms; t++)
-
543  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
+
364 int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
+
365 
+
366  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
+
367  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
+
368  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
+
369  return outcome;
+
370 }
+
371 
+
372 int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb) {
+
373 
+
374  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
+
375  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
+
376  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
+
377  return outcome;
+
378 }
+
379 
+ +
381 
+
382  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
+
383  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
+
384  return innerProdMag;
+
385 }
+
386 
+
387 void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2) {
+
388 
+
389  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
+
390  u.real[0][0]=1;
+
391  u.real[3][3]=1;
+
392  u.real[1][1] = .5; u.imag[1][1] = .5;
+
393  u.real[1][2] = .5; u.imag[1][2] =-.5;
+
394  u.real[2][1] = .5; u.imag[2][1] =-.5;
+
395  u.real[2][2] = .5; u.imag[2][2] = .5;
+
396 
+
397  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
+
398 }
+
399 
+
400 void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2) {
+
401 
+
402  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
+
403  u.real[0][0]=1;
+
404  u.real[3][3]=1;
+
405  u.real[1][1] = .5; u.imag[1][1] =-.5;
+
406  u.real[1][2] = .5; u.imag[1][2] = .5;
+
407  u.real[2][1] = .5; u.imag[2][1] = .5;
+
408  u.real[2][2] = .5; u.imag[2][2] =-.5;
+
409 
+
410  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
+
411 }
+
412 
+ +
415  Qureg qureg, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle,
+
416  int applyConj
+
417 ) {
+
418  qreal fac = 1/sqrt(2);
+
419  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
+
420  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
+
421  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
+
422  Complex uRyBeta = {.real = -fac, .imag = 0};
+
423 
+
424  // mask may be modified to remove superfluous Identity ops
+
425  long long int mask = getQubitBitMask(targetQubits, numTargets);
+
426 
+
427  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
+
428  for (int t=0; t < numTargets; t++) {
+
429  if (targetPaulis[t] == PAULI_I)
+
430  mask -= 1LL << targetQubits[t]; // remove target from mask
+
431  if (targetPaulis[t] == PAULI_X)
+
432  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
+
433  if (targetPaulis[t] == PAULI_Y)
+
434  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
+
435  // (targetPaulis[t] == 3) is Z basis
+
436  }
+
437 
+
438  // does nothing if there are no qubits to 'rotate'
+
439  if (mask != 0)
+
440  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
+
441 
+
442  // undo X and Y basis rotations
+
443  uRxBeta.imag *= -1;
+
444  uRyBeta.real *= -1;
+
445  for (int t=0; t < numTargets; t++) {
+
446  if (targetPaulis[t] == PAULI_X)
+
447  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
+
448  if (targetPaulis[t] == PAULI_Y)
+
449  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
+
450  }
+
451 }
+
452 
+ +
454  Qureg qureg, long long int ctrlMask, int* targetQubits, enum pauliOpType* targetPaulis, int numTargets, qreal angle,
+
455  int applyConj
+
456 ) {
+
457  qreal fac = 1/sqrt(2);
+
458  qreal sgn = (applyConj)? 1 : -1;
+
459  ComplexMatrix2 uRx = {.real={{fac,0},{0,fac}}, .imag={{0,sgn*fac},{sgn*fac,0}}}; // Rx(pi/2)* rotates Z -> Y
+
460  ComplexMatrix2 uRy = {.real={{fac,fac},{-fac,fac}}, .imag={{0,0},{0,0}}}; // Ry(-pi/2) rotates Z -> X
+
461 
+
462  // this function is controlled on the all-one state, so no ctrl flips
+
463  long long int ctrlFlipMask = 0;
+
464 
+
465  // mask may be modified to remove superfluous Identity ops
+
466  long long int targMask = getQubitBitMask(targetQubits, numTargets);
+
467 
+
468  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
+
469  for (int t=0; t < numTargets; t++) {
+
470  if (targetPaulis[t] == PAULI_I)
+
471  targMask -= 1LL << targetQubits[t]; // remove target from mask
+
472  if (targetPaulis[t] == PAULI_X)
+
473  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
+
474  if (targetPaulis[t] == PAULI_Y)
+
475  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
+
476  // (targetPaulis[t] == 3) is Z basis
+
477  }
+
478 
+
479  // does nothing if there are no qubits to 'rotate'
+
480  if (targMask != 0)
+
481  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, (applyConj)? -angle : angle);
+
482 
+
483  // undo X and Y basis rotations
+
484  uRx.imag[0][1] *= -1; uRx.imag[1][0] *= -1;
+
485  uRy.real[0][1] *= -1; uRy.real[1][0] *= -1;
+
486  for (int t=0; t < numTargets; t++) {
+
487  if (targetPaulis[t] == PAULI_X)
+
488  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
+
489  if (targetPaulis[t] == PAULI_Y)
+
490  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
+
491  }
+
492 }
+
493 
+
494 /* produces both pauli|qureg> or pauli * qureg (as a density matrix) */
+
495 void statevec_applyPauliProd(Qureg workspace, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets) {
+
496 
+
497  for (int i=0; i < numTargets; i++) {
+
498  // (pauliCodes[i] == PAULI_I) applies no operation
+
499  if (pauliCodes[i] == PAULI_X)
+
500  statevec_pauliX(workspace, targetQubits[i]);
+
501  if (pauliCodes[i] == PAULI_Y)
+
502  statevec_pauliY(workspace, targetQubits[i]);
+
503  if (pauliCodes[i] == PAULI_Z)
+
504  statevec_pauliZ(workspace, targetQubits[i]);
+
505  }
+
506 }
+
507 
+
508 // <pauli> = <qureg|pauli|qureg> = qureg . pauli(qureg)
+
509 qreal statevec_calcExpecPauliProd(Qureg qureg, int* targetQubits, enum pauliOpType* pauliCodes, int numTargets, Qureg workspace) {
+
510 
+
511  statevec_cloneQureg(workspace, qureg);
+
512  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
+
513 
+
514  // compute the expected value
+
515  qreal value;
+
516  if (qureg.isDensityMatrix)
+
517  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
+
518  else
+
519  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
+
520 
+
521  return value;
+
522 }
+
523 
+
524 qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg workspace) {
+
525 
+
526  int numQb = qureg.numQubitsRepresented;
+
527  int targs[100]; // [numQb];
+
528  for (int q=0; q < numQb; q++)
+
529  targs[q] = q;
+
530 
+
531  qreal value = 0;
+
532  for (int t=0; t < numSumTerms; t++)
+
533  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
+
534 
+
535  return value;
+
536 }
+
537 
+
538 void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg) {
+
539 
+
540  int numQb = inQureg.numQubitsRepresented;
+
541  int targs[100]; // [numQb];
+
542  for (int q=0; q < numQb; q++)
+
543  targs[q] = q;
544 
-
545  return value;
-
546 }
-
547 
-
548 void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType* allCodes, qreal* termCoeffs, int numSumTerms, Qureg outQureg) {
-
549 
-
550  int numQb = inQureg.numQubitsRepresented;
-
551  int targs[numQb];
-
552  for (int q=0; q < numQb; q++)
-
553  targs[q] = q;
-
554 
-
555  statevec_initBlankState(outQureg);
-
556 
-
557  for (int t=0; t < numSumTerms; t++) {
-
558  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
-
559  Complex iden = (Complex) {.real=1, .imag=0};
-
560  Complex zero = (Complex) {.real=0, .imag=0};
-
561 
-
562  // outQureg += coef paulis(inQureg)
-
563  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
564  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
-
565 
-
566  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
-
567  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
568  }
-
569 }
-
570 
-
571 void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
572 
-
573  long long int ctrlMask = 0;
-
574  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
575 }
-
576 
-
577 void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
-
578 
-
579  long long int ctrlMask = 1LL << controlQubit;
-
580  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
581 }
-
582 
-
583 void statevec_multiQubitUnitary(Qureg qureg, int* targets, int numTargets, ComplexMatrixN u) {
-
584 
-
585  long long int ctrlMask = 0;
-
586  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
587 }
-
588 
-
589 void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targets, int numTargets, ComplexMatrixN u) {
-
590 
-
591  long long int ctrlMask = 1LL << ctrl;
-
592  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
593 }
-
594 
-
595 #define macro_populateKrausOperator(superOp, ops, numOps, opDim) \
-
596  /* clear the superop */ \
-
597  for (int r=0; r < (opDim)*(opDim); r++) \
-
598  for (int c=0; c < (opDim)*(opDim); c++) { \
-
599  superOp->real[r][c] = 0; \
-
600  superOp->imag[r][c] = 0; \
-
601  } \
-
602  /* add each op's contribution to the superop */ \
-
603  for (int n=0; n<(numOps); n++) \
-
604  /* superop += conjugate(op) (x) op, where (x) is a tensor product */ \
-
605  for (int i = 0; i < (opDim); i++) \
-
606  for (int j = 0; j < (opDim); j++) \
-
607  for (int k = 0; k < (opDim); k++) \
-
608  for (int l = 0; l < (opDim); l++) { \
-
609  superOp->real[i*(opDim) + k][j*(opDim) + l] += \
-
610  ops[n].real[i][j]*ops[n].real[k][l] + \
-
611  ops[n].imag[i][j]*ops[n].imag[k][l]; \
-
612  superOp->imag[i*(opDim) + k][j*(opDim) + l] += \
-
613  ops[n].real[i][j]*ops[n].imag[k][l] - \
-
614  ops[n].imag[i][j]*ops[n].real[k][l]; \
-
615  }
-
616 
- -
618  int opDim = 2;
-
619  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
620 }
- -
622  int opDim = 4;
-
623  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
545  statevec_initBlankState(outQureg);
+
546 
+
547  for (int t=0; t < numSumTerms; t++) {
+
548  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
+
549  Complex iden = (Complex) {.real=1, .imag=0};
+
550  Complex zero = (Complex) {.real=0, .imag=0};
+
551 
+
552  // outQureg += coef paulis(inQureg)
+
553  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
+
554  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
+
555 
+
556  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
+
557  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
+
558  }
+
559 }
+
560 
+
561 void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
+
562 
+
563  long long int ctrlMask = 0;
+
564  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
+
565 }
+
566 
+
567 void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u) {
+
568 
+
569  long long int ctrlMask = 1LL << controlQubit;
+
570  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
+
571 }
+
572 
+
573 void statevec_multiQubitUnitary(Qureg qureg, int* targets, int numTargets, ComplexMatrixN u) {
+
574 
+
575  long long int ctrlMask = 0;
+
576  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
+
577 }
+
578 
+
579 void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int* targets, int numTargets, ComplexMatrixN u) {
+
580 
+
581  long long int ctrlMask = 1LL << ctrl;
+
582  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
+
583 }
+
584 
+
585 #define macro_populateKrausOperator(superOp, ops, numOps, opDim) \
+
586  /* clear the superop */ \
+
587  for (int r=0; r < (opDim)*(opDim); r++) \
+
588  for (int c=0; c < (opDim)*(opDim); c++) { \
+
589  superOp->real[r][c] = 0; \
+
590  superOp->imag[r][c] = 0; \
+
591  } \
+
592  /* add each op's contribution to the superop */ \
+
593  for (int n=0; n<(numOps); n++) \
+
594  /* superop += conjugate(op) (x) op, where (x) is a tensor product */ \
+
595  for (int i = 0; i < (opDim); i++) \
+
596  for (int j = 0; j < (opDim); j++) \
+
597  for (int k = 0; k < (opDim); k++) \
+
598  for (int l = 0; l < (opDim); l++) { \
+
599  superOp->real[i*(opDim) + k][j*(opDim) + l] += \
+
600  ops[n].real[i][j]*ops[n].real[k][l] + \
+
601  ops[n].imag[i][j]*ops[n].imag[k][l]; \
+
602  superOp->imag[i*(opDim) + k][j*(opDim) + l] += \
+
603  ops[n].real[i][j]*ops[n].imag[k][l] - \
+
604  ops[n].imag[i][j]*ops[n].real[k][l]; \
+
605  }
+
606 
+ +
608  int opDim = 2;
+
609  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
610 }
+ +
612  int opDim = 4;
+
613  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
614 }
+ +
616  int opDim = 1 << ops[0].numQubits;
+
617  macro_populateKrausOperator(superOp, ops, numOps, opDim);
+
618 }
+
619 
+
620 void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp) {
+
621 
+
622  long long int ctrlMask = 0;
+
623  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, target, target + qureg.numQubitsRepresented, superOp);
624 }
- -
626  int opDim = 1 << ops[0].numQubits;
-
627  macro_populateKrausOperator(superOp, ops, numOps, opDim);
-
628 }
-
629 
-
630 void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp) {
-
631 
-
632  long long int ctrlMask = 0;
-
633  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, target, target + qureg.numQubitsRepresented, superOp);
-
634 }
-
635 
-
636 void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp) {
-
637 
-
638  long long int ctrlMask = 0;
-
639  int numQb = qureg.numQubitsRepresented;
-
640  int allTargets[4] = {target1, target2, target1+numQb, target2+numQb};
-
641  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 4, superOp);
+
625 
+
626 void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp) {
+
627 
+
628  long long int ctrlMask = 0;
+
629  int numQb = qureg.numQubitsRepresented;
+
630  int allTargets[4] = {target1, target2, target1+numQb, target2+numQb};
+
631  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 4, superOp);
+
632 }
+
633 
+
634 void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp) {
+
635  long long int ctrlMask = 0;
+
636  int allTargets[200]; // [2*numTargets];
+
637  for (int t=0; t < numTargets; t++) {
+
638  allTargets[t] = targets[t];
+
639  allTargets[t+numTargets] = targets[t] + qureg.numQubitsRepresented;
+
640  }
+
641  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 2*numTargets, superOp);
642 }
643 
-
644 void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp) {
-
645  long long int ctrlMask = 0;
-
646  int allTargets[2*numTargets];
-
647  for (int t=0; t < numTargets; t++) {
-
648  allTargets[t] = targets[t];
-
649  allTargets[t+numTargets] = targets[t] + qureg.numQubitsRepresented;
-
650  }
-
651  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, allTargets, 2*numTargets, superOp);
-
652 }
-
653 
-
654 void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps) {
-
655 
-
656  ComplexMatrix4 superOp;
-
657  populateKrausSuperOperator2(&superOp, ops, numOps);
-
658  densmatr_applyKrausSuperoperator(qureg, target, superOp);
-
659 }
-
660 
- -
662  int numQubits, qreal re[][1<<numQubits], qreal im[][1<<numQubits],
-
663  qreal** reStorage, qreal** imStorage
-
664 ) {
-
665  ComplexMatrixN m;
-
666  m.numQubits = numQubits;
-
667  m.real = reStorage;
-
668  m.imag = imStorage;
-
669 
-
670  int len = 1<<numQubits;
-
671  for (int i=0; i<len; i++) {
-
672  m.real[i] = re[i];
-
673  m.imag[i] = im[i];
-
674  }
-
675  return m;
-
676 }
-
677 #define macro_initialiseStackComplexMatrixN(matrix, numQubits, real, imag) \
-
678  /* reStorage_ and imStorage_ must not exist in calling scope */ \
-
679  qreal* reStorage_[1<<(numQubits)]; \
-
680  qreal* imStorage_[1<<(numQubits)]; \
-
681  matrix = bindArraysToStackComplexMatrixN((numQubits), real, imag, reStorage_, imStorage_);
-
682 
-
683 #define macro_allocStackComplexMatrixN(matrix, numQubits) \
-
684  /* reArr_, imArr_, reStorage_, and imStorage_ must not exist in calling scope */ \
-
685  qreal reArr_[1<<(numQubits)][1<<(numQubits)]; \
-
686  qreal imArr_[1<<(numQubits)][1<<(numQubits)]; \
-
687  macro_initialiseStackComplexMatrixN(matrix, (numQubits), reArr_, imArr_);
-
688 
-
689 void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps) {
-
690 
-
691  ComplexMatrixN superOp;
-
692  macro_allocStackComplexMatrixN(superOp, 4);
-
693  populateKrausSuperOperator4(&superOp, ops, numOps);
-
694  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
-
695 }
-
696 
-
697 void densmatr_mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps) {
-
698 
-
699  ComplexMatrixN superOp;
-
700 
-
701  /* superOp will contain 2^(4 numTargets) complex numbers.
-
702  * At double precision, superOp will cost additional memory:
-
703  * numTargs=1 -> 0.25 KiB
-
704  * numTargs=2 -> 4 KiB
-
705  * numTargs=3 -> 64 KiB
-
706  * numTargs=4 -> 1 MiB
-
707  * numTargs=5 -> 16 MiB.
-
708  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
-
709  * this costs at most double.
-
710  *
-
711  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
-
712  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
-
713  * for numTargets < 4, superOp will be kept in the stack, else in the heap
-
714  */
-
715 
-
716  if (numTargets < 4) {
-
717  // everything must live in 'if' since this macro declares local vars
-
718  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
-
719  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
720  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
721  }
-
722  else {
-
723  superOp = createComplexMatrixN(2*numTargets);
-
724  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
725  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
726  destroyComplexMatrixN(superOp);
-
727  }
-
728 }
-
729 
-
730 void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ) {
-
731 
-
732  // convert pauli probabilities into Kraus map
-
733  const int numOps = 4;
-
734  ComplexMatrix2 ops[numOps];
-
735  for (int n=0; n < numOps; n++)
-
736  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
-
737 
-
738  qreal facs[4] = { // literal numOps=4 for valid initialisation
-
739  sqrt(1-(probX + probY + probZ)),
-
740  sqrt(probX),
-
741  sqrt(probY),
-
742  sqrt(probZ)
-
743  };
-
744  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
-
745  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
-
746  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
-
747  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
-
748 
-
749  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
-
750 }
-
751 
-
752 void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse) {
-
753 
-
754  /* applies a first-order one-repetition approximation of exp(-i fac H)
-
755  * to qureg. Letting H = sum_j c_j h_j, it does this via
-
756  * exp(-i fac H) ~ prod_j exp(-i fac c_j h_j), where each inner exp
-
757  * is performed with multiRotatePauli (with pre-factor 2).
-
758  */
-
759 
-
760  // prepare targets for multiRotatePauli
-
761  // (all qubits; actual targets are determined by Pauli codes)
-
762  int vecTargs[hamil.numQubits];
-
763  int densTargs[hamil.numQubits];
-
764  for (int q=0; q<hamil.numQubits; q++) {
-
765  vecTargs[q] = q;
-
766  densTargs[q] = q + hamil.numQubits;
-
767  }
-
768 
-
769  for (int i=0; i<hamil.numSumTerms; i++) {
-
770 
-
771  int t=i;
-
772  if (reverse)
-
773  t=hamil.numSumTerms-1-i;
-
774 
-
775  qreal angle = 2*fac*hamil.termCoeffs[t];
-
776 
- -
778  qureg, vecTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
779  hamil.numQubits, angle, 0);
-
780 
-
781  if (qureg.isDensityMatrix)
- -
783  qureg, densTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
-
784  hamil.numQubits, angle, 1);
-
785 
-
786  // record qasm
-
787  char buff[1024];
-
788  int b=0;
-
789  for (int q=0; q<hamil.numQubits; q++) {
-
790  enum pauliOpType op = hamil.pauliCodes[q + t*hamil.numQubits];
-
791 
-
792  char p = 'I';
-
793  if (op == PAULI_X) p = 'X';
-
794  if (op == PAULI_Y) p = 'Y';
-
795  if (op == PAULI_Z) p = 'Z';
-
796  buff[b++] = p;
-
797  buff[b++] = ' ';
-
798  }
-
799  buff[b] = '\0';
-
800 
-
801  qasm_recordComment(qureg,
-
802  "Here, a multiRotatePauli with angle %g and paulis %s was applied.",
-
803  angle, buff);
-
804  }
-
805 }
-
806 
-
807 void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order) {
-
808 
-
809  if (order == 1) {
-
810  applyExponentiatedPauliHamil(qureg, hamil, time, 0);
-
811  }
-
812  else if (order == 2) {
-
813  applyExponentiatedPauliHamil(qureg, hamil, time/2., 0);
-
814  applyExponentiatedPauliHamil(qureg, hamil, time/2., 1);
-
815  }
-
816  else {
-
817  qreal p = 1. / (4 - pow(4, 1./(order-1)));
-
818  int lower = order-2;
-
819  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
820  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
821  applySymmetrizedTrotterCircuit(qureg, hamil, (1-4*p)*time, lower);
-
822  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
-
823  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
644 void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps) {
+
645 
+
646  ComplexMatrix4 superOp;
+
647  populateKrausSuperOperator2(&superOp, ops, numOps);
+
648  densmatr_applyKrausSuperoperator(qureg, target, superOp);
+
649 }
+
650 
+
651 #ifndef _WIN32
+ +
653  int numQubits, qreal re[][1<<numQubits], qreal im[][1<<numQubits],
+
654  qreal** reStorage, qreal** imStorage
+
655 ) {
+
656  ComplexMatrixN m;
+
657  m.numQubits = numQubits;
+
658  m.real = reStorage;
+
659  m.imag = imStorage;
+
660 
+
661  int len = 1<<numQubits;
+
662  for (int i=0; i<len; i++) {
+
663  m.real[i] = re[i];
+
664  m.imag[i] = im[i];
+
665  }
+
666  return m;
+
667 }
+
668 
+
669 #define macro_initialiseStackComplexMatrixN(matrix, numQubits, real, imag) \
+
670  /* reStorage_ and imStorage_ must not exist in calling scope */ \
+
671  qreal* reStorage_[1<<(numQubits)]; \
+
672  qreal* imStorage_[1<<(numQubits)]; \
+
673  matrix = bindArraysToStackComplexMatrixN((numQubits), real, imag, reStorage_, imStorage_);
+
674 
+
675 #define macro_allocStackComplexMatrixN(matrix, numQubits) \
+
676  /* reArr_, imArr_, reStorage_, and imStorage_ must not exist in calling scope */ \
+
677  qreal reArr_[1<<(numQubits)][1<<(numQubits)]; \
+
678  qreal imArr_[1<<(numQubits)][1<<(numQubits)]; \
+
679  macro_initialiseStackComplexMatrixN(matrix, (numQubits), reArr_, imArr_);
+
680 #endif
+
681 
+
682 void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps) {
+
683 
+
684  // if NOT on Windows, allocate ComplexN on stack
+
685  #ifndef _WIN32
+
686  ComplexMatrixN superOp;
+
687  macro_allocStackComplexMatrixN(superOp, 4);
+
688  populateKrausSuperOperator4(&superOp, ops, numOps);
+
689  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
+
690 
+
691  // but on Windows, we MUST allocated dynamically
+
692  #else
+ +
694  populateKrausSuperOperator4(&superOp, ops, numOps);
+
695  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
+
696  destroyComplexMatrixN(superOp);
+
697 
+
698  #endif
+
699 }
+
700 
+
701 void densmatr_mixMultiQubitKrausMap(Qureg qureg, int* targets, int numTargets, ComplexMatrixN* ops, int numOps) {
+
702 
+
703  ComplexMatrixN superOp;
+
704 
+
705  /* superOp will contain 2^(4 numTargets) complex numbers.
+
706  * At double precision, superOp will cost additional memory:
+
707  * numTargs=1 -> 0.25 KiB
+
708  * numTargs=2 -> 4 KiB
+
709  * numTargs=3 -> 64 KiB
+
710  * numTargs=4 -> 1 MiB
+
711  * numTargs=5 -> 16 MiB.
+
712  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
+
713  * this costs at most double.
+
714  *
+
715  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
+
716  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
+
717  * for numTargets < 4, superOp will be kept in the stack, else in the heap
+
718  */
+
719 
+
720  // if NOT on Windows, allocate ComplexN on stack depending on size
+
721  #ifndef _WIN32
+
722  if (numTargets < 4) {
+
723  // everything must live in 'if' since this macro declares local vars
+
724  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
+
725  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
726  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
727  }
+
728  else {
+
729  superOp = createComplexMatrixN(2*numTargets);
+
730  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
731  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
732  destroyComplexMatrixN(superOp);
+
733  }
+
734  // on Windows, we must always create in heap
+
735  #else
+
736  superOp = createComplexMatrixN(2*numTargets);
+
737  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
738  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
739  destroyComplexMatrixN(superOp);
+
740  #endif
+
741 }
+
742 
+
743 void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ) {
+
744 
+
745  // convert pauli probabilities into Kraus map
+
746  const int numOps = 4;
+
747  ComplexMatrix2 ops[4]; // [numOps];
+
748  for (int n=0; n < numOps; n++)
+
749  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
+
750 
+
751  qreal facs[4] = { // literal numOps=4 for valid initialisation
+
752  sqrt(1-(probX + probY + probZ)),
+
753  sqrt(probX),
+
754  sqrt(probY),
+
755  sqrt(probZ)
+
756  };
+
757  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
+
758  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
+
759  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
+
760  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
+
761 
+
762  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
+
763 }
+
764 
+
765 void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse) {
+
766 
+
767  /* applies a first-order one-repetition approximation of exp(-i fac H)
+
768  * to qureg. Letting H = sum_j c_j h_j, it does this via
+
769  * exp(-i fac H) ~ prod_j exp(-i fac c_j h_j), where each inner exp
+
770  * is performed with multiRotatePauli (with pre-factor 2).
+
771  */
+
772 
+
773  // prepare targets for multiRotatePauli
+
774  // (all qubits; actual targets are determined by Pauli codes)
+
775  int vecTargs[100]; // [hamil.numQubits];
+
776  int densTargs[100]; // [hamil.numQubits];
+
777  for (int q=0; q<hamil.numQubits; q++) {
+
778  vecTargs[q] = q;
+
779  densTargs[q] = q + hamil.numQubits;
+
780  }
+
781 
+
782  for (int i=0; i<hamil.numSumTerms; i++) {
+
783 
+
784  int t=i;
+
785  if (reverse)
+
786  t=hamil.numSumTerms-1-i;
+
787 
+
788  qreal angle = 2*fac*hamil.termCoeffs[t];
+
789 
+ +
791  qureg, vecTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
+
792  hamil.numQubits, angle, 0);
+
793 
+
794  if (qureg.isDensityMatrix)
+ +
796  qureg, densTargs, &(hamil.pauliCodes[t*hamil.numQubits]),
+
797  hamil.numQubits, angle, 1);
+
798 
+
799  // record qasm
+
800  char buff[1024];
+
801  int b=0;
+
802  for (int q=0; q<hamil.numQubits; q++) {
+
803  enum pauliOpType op = hamil.pauliCodes[q + t*hamil.numQubits];
+
804 
+
805  char p = 'I';
+
806  if (op == PAULI_X) p = 'X';
+
807  if (op == PAULI_Y) p = 'Y';
+
808  if (op == PAULI_Z) p = 'Z';
+
809  buff[b++] = p;
+
810  buff[b++] = ' ';
+
811  }
+
812  buff[b] = '\0';
+
813 
+
814  qasm_recordComment(qureg,
+
815  "Here, a multiRotatePauli with angle %g and paulis %s was applied.",
+
816  angle, buff);
+
817  }
+
818 }
+
819 
+
820 void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order) {
+
821 
+
822  if (order == 1) {
+
823  applyExponentiatedPauliHamil(qureg, hamil, time, 0);
824  }
-
825 }
-
826 
-
827 void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps) {
-
828 
-
829  if (time == 0)
-
830  return;
-
831 
-
832  for (int r=0; r<reps; r++)
-
833  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
-
834 }
-
835 
-
836 void agnostic_applyQFT(Qureg qureg, int* qubits, int numQubits) {
-
837 
-
838  int densShift = qureg.numQubitsRepresented;
-
839 
-
840  // start with top/left-most qubit, work down
-
841  for (int q=numQubits-1; q >= 0; q--) {
-
842 
-
843  // H
-
844  statevec_hadamard(qureg, qubits[q]);
-
845  if (qureg.isDensityMatrix)
-
846  statevec_hadamard(qureg, qubits[q] + densShift);
-
847  qasm_recordGate(qureg, GATE_HADAMARD, qubits[q]);
-
848 
-
849  if (q == 0)
-
850  break;
-
851 
-
852  // succession of C-phases, control on qubits[q], targeting each of
-
853  // qubits[q-1], qubits[q-1], ... qubits[0]. This can be expressed by
-
854  // a single invocation of applyNamedPhaseFunc product
+
825  else if (order == 2) {
+
826  applyExponentiatedPauliHamil(qureg, hamil, time/2., 0);
+
827  applyExponentiatedPauliHamil(qureg, hamil, time/2., 1);
+
828  }
+
829  else {
+
830  qreal p = 1. / (4 - pow(4, 1./(order-1)));
+
831  int lower = order-2;
+
832  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
833  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
834  applySymmetrizedTrotterCircuit(qureg, hamil, (1-4*p)*time, lower);
+
835  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
836  applySymmetrizedTrotterCircuit(qureg, hamil, p*time, lower);
+
837  }
+
838 }
+
839 
+
840 void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps) {
+
841 
+
842  if (time == 0)
+
843  return;
+
844 
+
845  for (int r=0; r<reps; r++)
+
846  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
+
847 }
+
848 
+
849 void agnostic_applyQFT(Qureg qureg, int* qubits, int numQubits) {
+
850 
+
851  int densShift = qureg.numQubitsRepresented;
+
852 
+
853  // start with top/left-most qubit, work down
+
854  for (int q=numQubits-1; q >= 0; q--) {
855 
-
856  int numRegs = 2;
-
857  int numQubitsPerReg[2] = {q, 1};
-
858  int regs[q+1];
-
859  for (int i=0; i<q+1; i++)
-
860  regs[i] = qubits[i]; // qubits[q] is in own register
+
856  // H
+
857  statevec_hadamard(qureg, qubits[q]);
+
858  if (qureg.isDensityMatrix)
+
859  statevec_hadamard(qureg, qubits[q] + densShift);
+
860  qasm_recordGate(qureg, GATE_HADAMARD, qubits[q]);
861 
-
862  int numParams = 1;
-
863  qreal params[1] = { M_PI / (1 << q) };
+
862  if (q == 0)
+
863  break;
864 
-
865  int conj = 0;
- -
867  qureg, regs, numQubitsPerReg, numRegs,
-
868  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
869  NULL, NULL, 0,
-
870  conj);
-
871  if (qureg.isDensityMatrix) {
-
872  conj = 1;
-
873  shiftSubregIndices(regs, numQubitsPerReg, numRegs, densShift);
- -
875  qureg, regs, numQubitsPerReg, numRegs,
-
876  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
877  NULL, NULL, 0,
-
878  conj);
-
879  shiftSubregIndices(regs, numQubitsPerReg, numRegs, - densShift);
-
880  }
- -
882  qureg, regs, numQubitsPerReg, numRegs,
-
883  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
884  NULL, NULL, 0);
-
885  }
-
886 
-
887  // final swaps
-
888  for (int i=0; i<(numQubits/2); i++) {
-
889 
-
890  int qb1 = qubits[i];
-
891  int qb2 = qubits[numQubits-i-1];
-
892 
-
893  statevec_swapQubitAmps(qureg, qb1, qb2);
-
894  if (qureg.isDensityMatrix)
-
895  statevec_swapQubitAmps(qureg, qb1 + densShift, qb2 + densShift);
-
896  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
-
897  }
-
898 }
-
899 
-
900 #ifdef __cplusplus
-
901 }
-
902 #endif
+
865  // succession of C-phases, control on qubits[q], targeting each of
+
866  // qubits[q-1], qubits[q-1], ... qubits[0]. This can be expressed by
+
867  // a single invocation of applyNamedPhaseFunc product
+
868 
+
869  int numRegs = 2;
+
870  int numQubitsPerReg[2] = {q, 1};
+
871  int regs[100]; // [q+1];
+
872  for (int i=0; i<q+1; i++)
+
873  regs[i] = qubits[i]; // qubits[q] is in own register
+
874 
+
875  int numParams = 1;
+
876  qreal params[1] = { M_PI / (1 << q) };
+
877 
+
878  int conj = 0;
+ +
880  qureg, regs, numQubitsPerReg, numRegs,
+
881  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
882  NULL, NULL, 0,
+
883  conj);
+
884  if (qureg.isDensityMatrix) {
+
885  conj = 1;
+
886  shiftSubregIndices(regs, numQubitsPerReg, numRegs, densShift);
+ +
888  qureg, regs, numQubitsPerReg, numRegs,
+
889  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
890  NULL, NULL, 0,
+
891  conj);
+
892  shiftSubregIndices(regs, numQubitsPerReg, numRegs, - densShift);
+
893  }
+ +
895  qureg, regs, numQubitsPerReg, numRegs,
+
896  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
897  NULL, NULL, 0);
+
898  }
+
899 
+
900  // final swaps
+
901  for (int i=0; i<(numQubits/2); i++) {
+
902 
+
903  int qb1 = qubits[i];
+
904  int qb2 = qubits[numQubits-i-1];
+
905 
+
906  statevec_swapQubitAmps(qureg, qb1, qb2);
+
907  if (qureg.isDensityMatrix)
+
908  statevec_swapQubitAmps(qureg, qb1 + densShift, qb2 + densShift);
+
909  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
+
910  }
+
911 }
+
912 
+
913 #ifdef __cplusplus
+
914 }
+
915 #endif
-
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:264
+
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:254
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
-
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:278
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:271
+
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:268
+
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:261
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:306
-
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
void reportQuregParams(Qureg qureg)
Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.
Definition: QuEST_common.c:247
-
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:836
+
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:296
+
void reportQuregParams(Qureg qureg)
Report metainformation about a set of qubits: number of qubits, number of probability amplitudes.
Definition: QuEST_common.c:237
+
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:849
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:99
qreal real[4][4]
Definition: QuEST.h:177
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:654
+
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:644
@ PAULI_Z
Definition: QuEST.h:96
-
void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
Definition: QuEST_common.c:752
-
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:621
-
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:625
-
void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
Definition: QuEST_common.c:463
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1356
+
void applyExponentiatedPauliHamil(Qureg qureg, PauliHamil hamil, qreal fac, int reverse)
Definition: QuEST_common.c:765
+
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:611
+
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:615
+
void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
Definition: QuEST_common.c:453
+
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1369
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:156
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:519
-
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:577
+
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:509
+
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:567
@ PAULI_I
Definition: QuEST.h:96
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1335
-
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:534
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:571
-
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:299
+
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1348
+
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:524
+
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:561
+
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:289
qreal z
Definition: QuEST.h:200
ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
Definition: QuEST_common.c:110
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
-
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:505
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3277
+
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:495
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3316
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void seedQuEST(unsigned long int *seedArray, int numSeeds)
numSeeds <= 64
Definition: QuEST_common.c:222
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:697
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:701
Complex getConjugateScalar(Complex scalar)
Definition: QuEST_common.c:91
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
Definition: QuEST_common.c:105
@@ -985,108 +999,108 @@
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ UNSIGNED
Definition: QuEST.h:269
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:120
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:661
+
void statevec_pauliY(Qureg qureg, int targetQubit)
+
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:652
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
-
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:589
-
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:390
+
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:579
+
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:380
#define qreal
-
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:683
-
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:397
+
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:675
+
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:387
@ PAULI_X
Definition: QuEST.h:96
-
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:258
-
void reportState(Qureg qureg)
Print the current state vector of probability amplitudes for a set of qubits to file.
Definition: QuEST_common.c:229
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:248
+
void reportState(Qureg qureg)
Print the current state vector of probability amplitudes for a set of qubits to file.
Definition: QuEST_common.c:219
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
qreal densmatr_calcTotalProb(Qureg qureg)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:239
qreal y
Definition: QuEST.h:200
unsigned long int hashString(char *str)
Definition: QuEST_common.c:185
qreal imag[2][2]
Definition: QuEST.h:140
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4406
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3319
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3358
qreal x
Definition: QuEST.h:200
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:168
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:827
-
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:630
+
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:840
+
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:620
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:285
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
-
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:617
+
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:275
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
+
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:607
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1561
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:324
+
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1572
+
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:314
qreal imag[4][4]
Definition: QuEST.h:178
void setConjugateMatrixN(ComplexMatrixN m)
Definition: QuEST_common.c:115
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:689
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:682
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
@ PAULI_Y
Definition: QuEST.h:96
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
double genrand_real1(void)
Definition: mt19937ar.c:150
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:424
+
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:414
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
-
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:583
+
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:573
qreal ** real
Definition: QuEST.h:189
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:340
-
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:548
+
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:330
+
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:538
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:331
-
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:292
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3965
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
+
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:321
+
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:282
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:4005
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
Definition: QuEST_common.c:161
long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
Definition: QuEST_common.c:60
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
Represents a system of qubits.
Definition: QuEST.h:322
-
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:374
+
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:364
qreal ** imag
Definition: QuEST.h:190
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:130
-
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:356
+
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:346
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
qreal real[2][2]
Definition: QuEST.h:139
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:312
+
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:302
int numQubits
Definition: QuEST.h:188
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
-
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:636
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3146
+
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:626
+
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3185
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
-
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:410
-
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:368
+
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:400
+
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:358
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
-
void statevec_pauliX(Qureg qureg, int targetQubit)
+
void statevec_pauliX(Qureg qureg, int targetQubit)
@ GATE_SWAP
Definition: QuEST_qasm.h:33
qreal real
Definition: QuEST.h:105
-
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:644
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:730
+
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:634
+
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:743
qreal imag
Definition: QuEST.h:106
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:70
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:362
-
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:347
-
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
Definition: QuEST_common.c:595
+
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:352
+
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:337
+
#define macro_populateKrausOperator(superOp, ops, numOps, opDim)
Definition: QuEST_common.c:585
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:179
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:318
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:308
#define M_PI
Definition: QuEST_common.c:41
-
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:807
+
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:820
void qasm_recordNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc funcName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:726
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:382
+
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:372
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:142
diff --git a/docs/QuEST__complex_8h.html b/docs/QuEST__complex_8h.html index b00d37cee..c0edaa6b6 100644 --- a/docs/QuEST__complex_8h.html +++ b/docs/QuEST__complex_8h.html @@ -27,7 +27,7 @@ diff --git a/docs/QuEST__complex_8h_source.html b/docs/QuEST__complex_8h_source.html index f169ce7b6..e2cc61eeb 100644 --- a/docs/QuEST__complex_8h_source.html +++ b/docs/QuEST__complex_8h_source.html @@ -27,7 +27,7 @@ diff --git a/docs/QuEST__cpu_8c.html b/docs/QuEST__cpu_8c.html index e76acf19f..e16f0628c 100644 --- a/docs/QuEST__cpu_8c.html +++ b/docs/QuEST__cpu_8c.html @@ -27,7 +27,7 @@ @@ -325,30 +325,30 @@

-

Definition at line 1335 of file QuEST_cpu.c.

-
1335  {
-
1336 
-
1337  // the 2^numQubits values will be evenly split between the env.numRanks nodes
-
1338  DiagonalOp op;
-
1339  op.numQubits = numQubits;
-
1340  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
1341  op.chunkId = env.rank;
-
1342  op.numChunks = env.numRanks;
-
1343 
-
1344  // allocate CPU memory (initialised to zero)
-
1345  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1346  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+

Definition at line 1346 of file QuEST_cpu.c.

+
1346  {
1347 
-
1348  // check cpu memory allocation was successful
-
1349  if ( !op.real || !op.imag ) {
-
1350  printf("Could not allocate memory!\n");
-
1351  exit(EXIT_FAILURE);
-
1352  }
-
1353 
-
1354  return op;
-
1355 }
+
1348  // the 2^numQubits values will be evenly split between the env.numRanks nodes
+
1349  DiagonalOp op;
+
1350  op.numQubits = numQubits;
+
1351  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
+
1352  op.chunkId = env.rank;
+
1353  op.numChunks = env.numRanks;
+
1354 
+
1355  // allocate CPU memory (initialised to zero)
+
1356  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1357  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1358 
+
1359  // check cpu memory allocation was successful
+
1360  if ( !op.real || !op.imag ) {
+
1361  printf("Could not allocate memory!\n");
+
1362  exit(EXIT_FAILURE);
+
1363  }
+
1364 
+
1365  return op;
+
1366 }
-

References DiagonalOp::chunkId, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

+

References DiagonalOp::chunkId, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

@@ -368,11 +368,11 @@

-

Definition at line 1357 of file QuEST_cpu.c.

-
1357  {
-
1358  free(op.real);
-
1359  free(op.imag);
-
1360 }
+

Definition at line 1368 of file QuEST_cpu.c.

+
1368  {
+
1369  free(op.real);
+
1370  free(op.imag);
+
1371 }

References DiagonalOp::imag, and DiagonalOp::real.

@@ -404,68 +404,68 @@

-

Definition at line 1366 of file QuEST_cpu.c.

-
1366  {
-
1367 
-
1368  /* each node modifies its op sub-partition, evaluating the full hamil
-
1369  * for every element in the sub-partition
-
1370  */
-
1371 
-
1372  // unpack op
-
1373  long long int offset = op.chunkId * op.numElemsPerChunk;
-
1374  long long int numElems = op.numElemsPerChunk;
-
1375  qreal* opRe = op.real;
-
1376  qreal* opIm = op.imag;
-
1377 
-
1378  // unpack hamil
-
1379  int numTerms = hamil.numSumTerms;
-
1380  int numQubits = hamil.numQubits;
-
1381  qreal* coeffs = hamil.termCoeffs;
-
1382  enum pauliOpType* codes = hamil.pauliCodes;
-
1383 
-
1384  // private OpenMP vars
-
1385  long long int i, globalInd;
-
1386  qreal elem;
-
1387  int t, q, isOddNumOnes, sign;
+

Definition at line 1377 of file QuEST_cpu.c.

+
1377  {
+
1378 
+
1379  /* each node modifies its op sub-partition, evaluating the full hamil
+
1380  * for every element in the sub-partition
+
1381  */
+
1382 
+
1383  // unpack op
+
1384  long long int offset = op.chunkId * op.numElemsPerChunk;
+
1385  long long int numElems = op.numElemsPerChunk;
+
1386  qreal* opRe = op.real;
+
1387  qreal* opIm = op.imag;
1388 
-
1389 # ifdef _OPENMP
-
1390 # pragma omp parallel \
-
1391  default (none) \
-
1392  shared (offset,numElems, opRe,opIm, numTerms,numQubits,coeffs,codes) \
-
1393  private (i,globalInd, elem, isOddNumOnes,t,q,sign)
-
1394 # endif
-
1395  {
-
1396 # ifdef _OPENMP
-
1397 # pragma omp for schedule (static)
-
1398 # endif
-
1399  for (i=0; i<numElems; i++) {
-
1400 
-
1401  globalInd = i + offset;
-
1402  elem = 0;
-
1403 
-
1404  // add every Hamiltonian coefficient to this element, either + or -
-
1405  for (t=0; t<numTerms; t++) {
-
1406 
-
1407  // determine parity of ones (in globalInd basis state) of the current term's targets
-
1408  isOddNumOnes = 0;
-
1409  for (q=0; q<numQubits; q++)
-
1410  if (codes[q + t*numQubits] == PAULI_Z)
-
1411  if (extractBit(q, globalInd))
-
1412  isOddNumOnes = !isOddNumOnes;
-
1413 
-
1414  // add +- term coeff (avoiding thread divergence)
-
1415  sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1)
-
1416  elem += coeffs[t] * sign;
-
1417  }
-
1418 
-
1419  opRe[i] = elem;
-
1420  opIm[i] = 0;
-
1421  }
-
1422  }
-
1423 
-
1424  // we don't synch to GPU, because in GPU mode, the GPU populates and synchs to RAM
-
1425  // agnostic_syncDiagonalOp(op);
-
1426 }
+
1389  // unpack hamil
+
1390  int numTerms = hamil.numSumTerms;
+
1391  int numQubits = hamil.numQubits;
+
1392  qreal* coeffs = hamil.termCoeffs;
+
1393  enum pauliOpType* codes = hamil.pauliCodes;
+
1394 
+
1395  // private OpenMP vars
+
1396  long long int i, globalInd;
+
1397  qreal elem;
+
1398  int t, q, isOddNumOnes, sign;
+
1399 
+
1400 # ifdef _OPENMP
+
1401 # pragma omp parallel \
+
1402  default (none) \
+
1403  shared (offset,numElems, opRe,opIm, numTerms,numQubits,coeffs,codes) \
+
1404  private (i,globalInd, elem, isOddNumOnes,t,q,sign)
+
1405 # endif
+
1406  {
+
1407 # ifdef _OPENMP
+
1408 # pragma omp for schedule (static)
+
1409 # endif
+
1410  for (i=0; i<numElems; i++) {
+
1411 
+
1412  globalInd = i + offset;
+
1413  elem = 0;
+
1414 
+
1415  // add every Hamiltonian coefficient to this element, either + or -
+
1416  for (t=0; t<numTerms; t++) {
+
1417 
+
1418  // determine parity of ones (in globalInd basis state) of the current term's targets
+
1419  isOddNumOnes = 0;
+
1420  for (q=0; q<numQubits; q++)
+
1421  if (codes[q + t*numQubits] == PAULI_Z)
+
1422  if (extractBit(q, globalInd))
+
1423  isOddNumOnes = !isOddNumOnes;
+
1424 
+
1425  // add +- term coeff (avoiding thread divergence)
+
1426  sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1)
+
1427  elem += coeffs[t] * sign;
+
1428  }
+
1429 
+
1430  opRe[i] = elem;
+
1431  opIm[i] = 0;
+
1432  }
+
1433  }
+
1434 
+
1435  // we don't synch to GPU, because in GPU mode, the GPU populates and synchs to RAM
+
1436  // agnostic_syncDiagonalOp(op);
+
1437 }

References DiagonalOp::chunkId, extractBit(), DiagonalOp::imag, DiagonalOp::numElemsPerChunk, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_Z, PauliHamil::pauliCodes, qreal, DiagonalOp::real, and PauliHamil::termCoeffs.

@@ -515,46 +515,46 @@

-

Definition at line 4188 of file QuEST_cpu.c.

-
4188  {
-
4189 
-
4190  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
4191  // these may be negative or above qureg.numAmpsPerChunk
-
4192  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
-
4193  long long int localEndInd = localStartInd + numElems; // exclusive
-
4194 
-
4195  // add this to a local index to get corresponding elem in reals & imags
-
4196  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
-
4197 
-
4198  // restrict these indices to fit into this chunk
-
4199  if (localStartInd < 0)
-
4200  localStartInd = 0;
-
4201  if (localEndInd > op.numElemsPerChunk)
-
4202  localEndInd = op.numElemsPerChunk;
-
4203  // they may now be out of order = no iterations
-
4204 
-
4205  // unpacking OpenMP vars
-
4206  long long int index;
-
4207  qreal* vecRe = op.real;
-
4208  qreal* vecIm = op.imag;
-
4209 
-
4210 # ifdef _OPENMP
-
4211 # pragma omp parallel \
-
4212  default (none) \
-
4213  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
-
4214  private (index)
-
4215 # endif
-
4216  {
-
4217 # ifdef _OPENMP
-
4218 # pragma omp for schedule (static)
-
4219 # endif
-
4220  // iterate these local inds - this might involve no iterations
-
4221  for (index=localStartInd; index < localEndInd; index++) {
-
4222  vecRe[index] = real[index + offset];
-
4223  vecIm[index] = imag[index + offset];
-
4224  }
-
4225  }
-
4226 }
+

Definition at line 4228 of file QuEST_cpu.c.

+
4228  {
+
4229 
+
4230  // local start/end indices of the given amplitudes, assuming they fit in this chunk
+
4231  // these may be negative or above qureg.numAmpsPerChunk
+
4232  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
+
4233  long long int localEndInd = localStartInd + numElems; // exclusive
+
4234 
+
4235  // add this to a local index to get corresponding elem in reals & imags
+
4236  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
+
4237 
+
4238  // restrict these indices to fit into this chunk
+
4239  if (localStartInd < 0)
+
4240  localStartInd = 0;
+
4241  if (localEndInd > op.numElemsPerChunk)
+
4242  localEndInd = op.numElemsPerChunk;
+
4243  // they may now be out of order = no iterations
+
4244 
+
4245  // unpacking OpenMP vars
+
4246  long long int index;
+
4247  qreal* vecRe = op.real;
+
4248  qreal* vecIm = op.imag;
+
4249 
+
4250 # ifdef _OPENMP
+
4251 # pragma omp parallel \
+
4252  default (none) \
+
4253  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
+
4254  private (index)
+
4255 # endif
+
4256  {
+
4257 # ifdef _OPENMP
+
4258 # pragma omp for schedule (static)
+
4259 # endif
+
4260  // iterate these local inds - this might involve no iterations
+
4261  for (index=localStartInd; index < localEndInd; index++) {
+
4262  vecRe[index] = real[index + offset];
+
4263  vecIm[index] = imag[index + offset];
+
4264  }
+
4265  }
+
4266 }

References DiagonalOp::chunkId, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, qreal, and DiagonalOp::real.

@@ -576,10 +576,10 @@

-

Definition at line 1362 of file QuEST_cpu.c.

-
1362  {
-
1363  // nothing to do on CPU
-
1364 }
+

Definition at line 1373 of file QuEST_cpu.c.

+
1373  {
+
1374  // nothing to do on CPU
+
1375 }

@@ -633,37 +633,37 @@

-

Definition at line 754 of file QuEST_cpu.c.

-
757  {
-
758  long long int numDubBlocks = numAmps / (2*blockSize);
-
759  long long int blockStartInd;
-
760 
-
761  if (normFirst) {
-
762  long long int dubBlockInd;
-
763 # ifdef _OPENMP
-
764 # pragma omp parallel for schedule (static) private (blockStartInd)
-
765 # endif
-
766  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
767  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
768  normaliseSomeAmps(qureg, norm, blockStartInd, blockSize); // |0><0|
-
769  zeroSomeAmps( qureg, blockStartInd + blockSize, blockSize);
-
770  }
-
771  } else {
-
772  long long int dubBlockInd;
-
773 # ifdef _OPENMP
-
774 # pragma omp parallel for schedule (static) private (blockStartInd)
-
775 # endif
-
776  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
777  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
778  zeroSomeAmps( qureg, blockStartInd, blockSize);
-
779  normaliseSomeAmps(qureg, norm, blockStartInd + blockSize, blockSize); // |1><1|
-
780  }
-
781  }
-
782 }
+

Definition at line 760 of file QuEST_cpu.c.

+
763  {
+
764  long long int numDubBlocks = numAmps / (2*blockSize);
+
765  long long int blockStartInd;
+
766 
+
767  if (normFirst) {
+
768  long long int dubBlockInd;
+
769 # ifdef _OPENMP
+
770 # pragma omp parallel for schedule (static) private (blockStartInd)
+
771 # endif
+
772  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
+
773  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
+
774  normaliseSomeAmps(qureg, norm, blockStartInd, blockSize); // |0><0|
+
775  zeroSomeAmps( qureg, blockStartInd + blockSize, blockSize);
+
776  }
+
777  } else {
+
778  long long int dubBlockInd;
+
779 # ifdef _OPENMP
+
780 # pragma omp parallel for schedule (static) private (blockStartInd)
+
781 # endif
+
782  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
+
783  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
+
784  zeroSomeAmps( qureg, blockStartInd, blockSize);
+
785  normaliseSomeAmps(qureg, norm, blockStartInd + blockSize, blockSize); // |1><1|
+
786  }
+
787  }
+
788 }
-

References normaliseSomeAmps(), and zeroSomeAmps().

+

References normaliseSomeAmps(), and zeroSomeAmps().

-

Referenced by densmatr_collapseToKnownProbOutcome().

+

Referenced by densmatr_collapseToKnownProbOutcome().

@@ -693,52 +693,52 @@

-

Definition at line 4042 of file QuEST_cpu.c.

-
4042  {
-
4043 
-
4044  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
-
4045  * Furthermore, since it's gauranteed each node contains an integer number of
-
4046  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
-
4047  * then we know iteration below begins at the 'top' of a column, and there is
-
4048  * no offset for op (pairStateVector)
-
4049  */
-
4050 
-
4051  long long int numAmps = qureg.numAmpsPerChunk;
-
4052  int opDim = (1 << op.numQubits);
-
4053 
-
4054  qreal* stateRe = qureg.stateVec.real;
-
4055  qreal* stateIm = qureg.stateVec.imag;
-
4056  qreal* opRe = qureg.pairStateVec.real;
-
4057  qreal* opIm = qureg.pairStateVec.imag;
-
4058 
-
4059  qreal a,b,c,d;
-
4060  long long int index;
-
4061 
-
4062 # ifdef _OPENMP
-
4063 # pragma omp parallel \
-
4064  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
-
4065  private (index, a,b,c,d)
-
4066 # endif
-
4067  {
-
4068 # ifdef _OPENMP
-
4069 # pragma omp for schedule (static)
-
4070 # endif
-
4071  for (index=0LL; index<numAmps; index++) {
-
4072  a = stateRe[index];
-
4073  b = stateIm[index];
-
4074  c = opRe[index % opDim];
-
4075  d = opIm[index % opDim];
-
4076 
-
4077  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
4078  stateRe[index] = a*c - b*d;
-
4079  stateIm[index] = a*d + b*c;
-
4080  }
-
4081  }
-
4082 }
+

Definition at line 4082 of file QuEST_cpu.c.

+
4082  {
+
4083 
+
4084  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
+
4085  * Furthermore, since it's gauranteed each node contains an integer number of
+
4086  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
+
4087  * then we know iteration below begins at the 'top' of a column, and there is
+
4088  * no offset for op (pairStateVector)
+
4089  */
+
4090 
+
4091  long long int numAmps = qureg.numAmpsPerChunk;
+
4092  int opDim = (1 << op.numQubits);
+
4093 
+
4094  qreal* stateRe = qureg.stateVec.real;
+
4095  qreal* stateIm = qureg.stateVec.imag;
+
4096  qreal* opRe = qureg.pairStateVec.real;
+
4097  qreal* opIm = qureg.pairStateVec.imag;
+
4098 
+
4099  qreal a,b,c,d;
+
4100  long long int index;
+
4101 
+
4102 # ifdef _OPENMP
+
4103 # pragma omp parallel \
+
4104  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
+
4105  private (index, a,b,c,d)
+
4106 # endif
+
4107  {
+
4108 # ifdef _OPENMP
+
4109 # pragma omp for schedule (static)
+
4110 # endif
+
4111  for (index=0LL; index<numAmps; index++) {
+
4112  a = stateRe[index];
+
4113  b = stateIm[index];
+
4114  c = opRe[index % opDim];
+
4115  d = opIm[index % opDim];
+
4116 
+
4117  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
4118  stateRe[index] = a*c - b*d;
+
4119  stateIm[index] = a*d + b*c;
+
4120  }
+
4121  }
+
4122 }

References Qureg::numAmpsPerChunk, DiagonalOp::numQubits, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_applyDiagonalOp().

+

Referenced by densmatr_applyDiagonalOp().

@@ -768,71 +768,71 @@

-

Definition at line 4127 of file QuEST_cpu.c.

-
4127  {
-
4128 
-
4129  /* since for every 1 element in \p op, there exists a column in \p qureg,
-
4130  * we know that the elements in \p op live on the same node as the
-
4131  * corresponding diagonal elements of \p qureg. This means, the problem is
-
4132  * embarrassingly parallelisable, and the code below works for both
-
4133  * serial and distributed modes.
-
4134  */
-
4135 
-
4136  // computes first local index containing a diagonal element
-
4137  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
4138  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
4139  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
4140  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
4141  long long int numAmps = qureg.numAmpsPerChunk;
-
4142 
-
4143  qreal* stateReal = qureg.stateVec.real;
-
4144  qreal* stateImag = qureg.stateVec.imag;
-
4145  qreal* opReal = op.real;
-
4146  qreal* opImag = op.imag;
-
4147 
-
4148  qreal expecRe = 0;
-
4149  qreal expecIm = 0;
-
4150 
-
4151  long long int stateInd;
-
4152  long long int opInd;
-
4153  qreal matRe, matIm, opRe, opIm;
-
4154 
-
4155  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
-
4156 
-
4157 # ifdef _OPENMP
-
4158 # pragma omp parallel \
-
4159  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
-
4160  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
-
4161  reduction ( +:expecRe, expecIm )
-
4162 # endif
-
4163  {
-
4164 # ifdef _OPENMP
-
4165 # pragma omp for schedule (static)
-
4166 # endif
-
4167  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
-
4168 
-
4169  matRe = stateReal[stateInd];
-
4170  matIm = stateImag[stateInd];
-
4171  opInd = (stateInd - localIndNextDiag) / diagSpacing;
-
4172  opRe = opReal[opInd];
-
4173  opIm = opImag[opInd];
-
4174 
-
4175  // (matRe + matIm i)(opRe + opIm i) =
-
4176  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
4177  expecRe += matRe * opRe - matIm * opIm;
-
4178  expecIm += matRe * opIm + matIm * opRe;
-
4179  }
-
4180  }
-
4181 
-
4182  Complex expecVal;
-
4183  expecVal.real = expecRe;
-
4184  expecVal.imag = expecIm;
-
4185  return expecVal;
-
4186 }
+

Definition at line 4167 of file QuEST_cpu.c.

+
4167  {
+
4168 
+
4169  /* since for every 1 element in \p op, there exists a column in \p qureg,
+
4170  * we know that the elements in \p op live on the same node as the
+
4171  * corresponding diagonal elements of \p qureg. This means, the problem is
+
4172  * embarrassingly parallelisable, and the code below works for both
+
4173  * serial and distributed modes.
+
4174  */
+
4175 
+
4176  // computes first local index containing a diagonal element
+
4177  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
+
4178  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
+
4179  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
4180  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
+
4181  long long int numAmps = qureg.numAmpsPerChunk;
+
4182 
+
4183  qreal* stateReal = qureg.stateVec.real;
+
4184  qreal* stateImag = qureg.stateVec.imag;
+
4185  qreal* opReal = op.real;
+
4186  qreal* opImag = op.imag;
+
4187 
+
4188  qreal expecRe = 0;
+
4189  qreal expecIm = 0;
+
4190 
+
4191  long long int stateInd;
+
4192  long long int opInd;
+
4193  qreal matRe, matIm, opRe, opIm;
+
4194 
+
4195  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
+
4196 
+
4197 # ifdef _OPENMP
+
4198 # pragma omp parallel \
+
4199  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
+
4200  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
+
4201  reduction ( +:expecRe, expecIm )
+
4202 # endif
+
4203  {
+
4204 # ifdef _OPENMP
+
4205 # pragma omp for schedule (static)
+
4206 # endif
+
4207  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
+
4208 
+
4209  matRe = stateReal[stateInd];
+
4210  matIm = stateImag[stateInd];
+
4211  opInd = (stateInd - localIndNextDiag) / diagSpacing;
+
4212  opRe = opReal[opInd];
+
4213  opIm = opImag[opInd];
+
4214 
+
4215  // (matRe + matIm i)(opRe + opIm i) =
+
4216  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
+
4217  expecRe += matRe * opRe - matIm * opIm;
+
4218  expecIm += matRe * opIm + matIm * opRe;
+
4219  }
+
4220  }
+
4221 
+
4222  Complex expecVal;
+
4223  expecVal.real = expecRe;
+
4224  expecVal.imag = expecIm;
+
4225  return expecVal;
+
4226 }

References Qureg::chunkId, Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

-

Referenced by densmatr_calcExpecDiagonalOp().

+

Referenced by densmatr_calcExpecDiagonalOp().

@@ -864,91 +864,91 @@

Definition at line 990 of file QuEST_cpu.c.

-
990  {
-
991 
-
992  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
-
993  * We only consult the attributes.
-
994  *
-
995  * qureg is a density matrix, and pureState is a statevector.
-
996  * Every node contains as many columns of qureg as amps by pureState.
-
997  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
-
998  * Ergo, this node contains columns:
-
999  * qureg.chunkID * pureState.numAmpsPerChunk to
-
1000  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
-
1001  *
-
1002  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
-
1003  * entire pureState state-vector
-
1004  */
-
1005 
-
1006  // unpack everything for OPENMP
-
1007  qreal* vecRe = qureg.pairStateVec.real;
-
1008  qreal* vecIm = qureg.pairStateVec.imag;
-
1009  qreal* densRe = qureg.stateVec.real;
-
1010  qreal* densIm = qureg.stateVec.imag;
-
1011 
-
1012  int row, col;
-
1013  int dim = (int) pureState.numAmpsTotal;
-
1014  int colsPerNode = (int) pureState.numAmpsPerChunk;
-
1015  // using only int, because density matrix has squared as many amps so its
-
1016  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
-
1017 
-
1018  // starting GLOBAL column index of the qureg columns on this node
-
1019  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
-
1020 
-
1021  qreal densElemRe, densElemIm;
-
1022  qreal prefacRe, prefacIm;
-
1023  qreal rowSumRe, rowSumIm;
-
1024  qreal vecElemRe, vecElemIm;
-
1025 
-
1026  // quantity computed by this node
-
1027  qreal globalSumRe = 0; // imag-component is assumed zero
+

Definition at line 1001 of file QuEST_cpu.c.

+
1001  {
+
1002 
+
1003  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
+
1004  * We only consult the attributes.
+
1005  *
+
1006  * qureg is a density matrix, and pureState is a statevector.
+
1007  * Every node contains as many columns of qureg as amps by pureState.
+
1008  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
+
1009  * Ergo, this node contains columns:
+
1010  * qureg.chunkID * pureState.numAmpsPerChunk to
+
1011  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
+
1012  *
+
1013  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
+
1014  * entire pureState state-vector
+
1015  */
+
1016 
+
1017  // unpack everything for OPENMP
+
1018  qreal* vecRe = qureg.pairStateVec.real;
+
1019  qreal* vecIm = qureg.pairStateVec.imag;
+
1020  qreal* densRe = qureg.stateVec.real;
+
1021  qreal* densIm = qureg.stateVec.imag;
+
1022 
+
1023  int row, col;
+
1024  int dim = (int) pureState.numAmpsTotal;
+
1025  int colsPerNode = (int) pureState.numAmpsPerChunk;
+
1026  // using only int, because density matrix has squared as many amps so its
+
1027  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
1028 
-
1029 # ifdef _OPENMP
-
1030 # pragma omp parallel \
-
1031  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
-
1032  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
-
1033  reduction ( +:globalSumRe )
-
1034 # endif
-
1035  {
-
1036 # ifdef _OPENMP
-
1037 # pragma omp for schedule (static)
-
1038 # endif
-
1039  // indices of my GLOBAL row
-
1040  for (row=0; row < dim; row++) {
-
1041 
-
1042  // single element of conj(pureState)
-
1043  prefacRe = vecRe[row];
-
1044  prefacIm = - vecIm[row];
-
1045 
-
1046  rowSumRe = 0;
-
1047  rowSumIm = 0;
-
1048 
-
1049  // indices of my LOCAL column
-
1050  for (col=0; col < colsPerNode; col++) {
-
1051 
-
1052  // my local density element
-
1053  densElemRe = densRe[row + dim*col];
-
1054  densElemIm = densIm[row + dim*col];
-
1055 
-
1056  // state-vector element
-
1057  vecElemRe = vecRe[startCol + col];
-
1058  vecElemIm = vecIm[startCol + col];
+
1029  // starting GLOBAL column index of the qureg columns on this node
+
1030  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
+
1031 
+
1032  qreal densElemRe, densElemIm;
+
1033  qreal prefacRe, prefacIm;
+
1034  qreal rowSumRe, rowSumIm;
+
1035  qreal vecElemRe, vecElemIm;
+
1036 
+
1037  // quantity computed by this node
+
1038  qreal globalSumRe = 0; // imag-component is assumed zero
+
1039 
+
1040 # ifdef _OPENMP
+
1041 # pragma omp parallel \
+
1042  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
+
1043  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
+
1044  reduction ( +:globalSumRe )
+
1045 # endif
+
1046  {
+
1047 # ifdef _OPENMP
+
1048 # pragma omp for schedule (static)
+
1049 # endif
+
1050  // indices of my GLOBAL row
+
1051  for (row=0; row < dim; row++) {
+
1052 
+
1053  // single element of conj(pureState)
+
1054  prefacRe = vecRe[row];
+
1055  prefacIm = - vecIm[row];
+
1056 
+
1057  rowSumRe = 0;
+
1058  rowSumIm = 0;
1059 
-
1060  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
-
1061  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
-
1062  }
-
1063 
-
1064  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
-
1065  }
-
1066  }
-
1067 
-
1068  return globalSumRe;
-
1069 }
+
1060  // indices of my LOCAL column
+
1061  for (col=0; col < colsPerNode; col++) {
+
1062 
+
1063  // my local density element
+
1064  densElemRe = densRe[row + dim*col];
+
1065  densElemIm = densIm[row + dim*col];
+
1066 
+
1067  // state-vector element
+
1068  vecElemRe = vecRe[startCol + col];
+
1069  vecElemIm = vecIm[startCol + col];
+
1070 
+
1071  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
+
1072  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
+
1073  }
+
1074 
+
1075  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
+
1076  }
+
1077  }
+
1078 
+
1079  return globalSumRe;
+
1080 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcFidelity().

+

Referenced by densmatr_calcFidelity().

@@ -980,44 +980,44 @@

Definition at line 923 of file QuEST_cpu.c.

-
923  {
-
924 
-
925  long long int index;
-
926  long long int numAmps = a.numAmpsPerChunk;
-
927 
-
928  qreal *aRe = a.stateVec.real;
-
929  qreal *aIm = a.stateVec.imag;
-
930  qreal *bRe = b.stateVec.real;
-
931  qreal *bIm = b.stateVec.imag;
-
932 
-
933  qreal trace = 0;
-
934  qreal difRe, difIm;
+

Definition at line 934 of file QuEST_cpu.c.

+
934  {
935 
-
936 # ifdef _OPENMP
-
937 # pragma omp parallel \
-
938  shared (aRe,aIm, bRe,bIm, numAmps) \
-
939  private (index,difRe,difIm) \
-
940  reduction ( +:trace )
-
941 # endif
-
942  {
-
943 # ifdef _OPENMP
-
944 # pragma omp for schedule (static)
-
945 # endif
-
946  for (index=0LL; index<numAmps; index++) {
-
947 
-
948  difRe = aRe[index] - bRe[index];
-
949  difIm = aIm[index] - bIm[index];
-
950  trace += difRe*difRe + difIm*difIm;
-
951  }
-
952  }
-
953 
-
954  return trace;
-
955 }
+
936  long long int index;
+
937  long long int numAmps = a.numAmpsPerChunk;
+
938 
+
939  qreal *aRe = a.stateVec.real;
+
940  qreal *aIm = a.stateVec.imag;
+
941  qreal *bRe = b.stateVec.real;
+
942  qreal *bIm = b.stateVec.imag;
+
943 
+
944  qreal trace = 0;
+
945  qreal difRe, difIm;
+
946 
+
947 # ifdef _OPENMP
+
948 # pragma omp parallel \
+
949  shared (aRe,aIm, bRe,bIm, numAmps) \
+
950  private (index,difRe,difIm) \
+
951  reduction ( +:trace )
+
952 # endif
+
953  {
+
954 # ifdef _OPENMP
+
955 # pragma omp for schedule (static)
+
956 # endif
+
957  for (index=0LL; index<numAmps; index++) {
+
958 
+
959  difRe = aRe[index] - bRe[index];
+
960  difIm = aIm[index] - bIm[index];
+
961  trace += difRe*difRe + difIm*difIm;
+
962  }
+
963  }
+
964 
+
965  return trace;
+
966 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcHilbertSchmidtDistance().

+

Referenced by densmatr_calcHilbertSchmidtDistance().

@@ -1049,40 +1049,40 @@

Definition at line 958 of file QuEST_cpu.c.

-
958  {
-
959 
-
960  long long int index;
-
961  long long int numAmps = a.numAmpsPerChunk;
-
962 
-
963  qreal *aRe = a.stateVec.real;
-
964  qreal *aIm = a.stateVec.imag;
-
965  qreal *bRe = b.stateVec.real;
-
966  qreal *bIm = b.stateVec.imag;
-
967 
-
968  qreal trace = 0;
-
969 
-
970 # ifdef _OPENMP
-
971 # pragma omp parallel \
-
972  shared (aRe,aIm, bRe,bIm, numAmps) \
-
973  private (index) \
-
974  reduction ( +:trace )
-
975 # endif
-
976  {
-
977 # ifdef _OPENMP
-
978 # pragma omp for schedule (static)
-
979 # endif
-
980  for (index=0LL; index<numAmps; index++) {
-
981  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
-
982  }
-
983  }
-
984 
-
985  return trace;
-
986 }
+

Definition at line 969 of file QuEST_cpu.c.

+
969  {
+
970 
+
971  long long int index;
+
972  long long int numAmps = a.numAmpsPerChunk;
+
973 
+
974  qreal *aRe = a.stateVec.real;
+
975  qreal *aIm = a.stateVec.imag;
+
976  qreal *bRe = b.stateVec.real;
+
977  qreal *bIm = b.stateVec.imag;
+
978 
+
979  qreal trace = 0;
+
980 
+
981 # ifdef _OPENMP
+
982 # pragma omp parallel \
+
983  shared (aRe,aIm, bRe,bIm, numAmps) \
+
984  private (index) \
+
985  reduction ( +:trace )
+
986 # endif
+
987  {
+
988 # ifdef _OPENMP
+
989 # pragma omp for schedule (static)
+
990 # endif
+
991  for (index=0LL; index<numAmps; index++) {
+
992  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
+
993  }
+
994  }
+
995 
+
996  return trace;
+
997 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcInnerProduct().

+

Referenced by densmatr_calcInnerProduct().

@@ -1124,81 +1124,81 @@

-

Definition at line 3576 of file QuEST_cpu.c.

-
3576  {
-
3577 
-
3578  // clear outcomeProbs (in parallel, in case it's large)
-
3579  long long int numOutcomeProbs = (1 << numQubits);
-
3580  long long int j;
-
3581 
-
3582 # ifdef _OPENMP
-
3583 # pragma omp parallel \
-
3584  default (none) \
-
3585  shared (numOutcomeProbs,outcomeProbs) \
-
3586  private (j)
-
3587 # endif
-
3588  {
-
3589 # ifdef _OPENMP
-
3590 # pragma omp for schedule (static)
-
3591 # endif
-
3592  for (j=0; j<numOutcomeProbs; j++)
-
3593  outcomeProbs[j] = 0;
-
3594  }
-
3595 
-
3596  // compute first local index containing a diagonal element
-
3597  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3598  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3599  long long int diagSpacing = 1LL + densityDim;
-
3600  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3601  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3602  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3603  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3604 
-
3605  // computes how many diagonals are contained in this chunk
-
3606  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3607  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3608  numDiagsInThisChunk -= 1;
-
3609 
-
3610  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3611  long long int basisStateInd; // current diagonal index being considered
-
3612  long long int index; // index in the local chunk
-
3613 
-
3614  int q;
-
3615  long long int outcomeInd;
-
3616  qreal *stateRe = qureg.stateVec.real;
+

Definition at line 3616 of file QuEST_cpu.c.

+
3616  {
3617 
-
3618 # ifdef _OPENMP
-
3619 # pragma omp parallel \
-
3620  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateRe, numDiagsInThisChunk, qubits,numQubits, outcomeProbs) \
-
3621  private (visitedDiags, basisStateInd, index, q,outcomeInd)
-
3622 # endif
-
3623  {
-
3624 # ifdef _OPENMP
-
3625 # pragma omp for schedule (static)
-
3626 # endif
-
3627  // sums the diagonal elems of the density matrix where measureQubit=0
-
3628  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3629 
-
3630  basisStateInd = numPrevDiags + visitedDiags;
-
3631  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3632 
-
3633  // determine outcome implied by basisStateInd
-
3634  outcomeInd = 0;
-
3635  for (q=0; q<numQubits; q++)
-
3636  outcomeInd += extractBit(qubits[q], basisStateInd) * (1LL << q);
-
3637 
-
3638  // atomicly update corresponding outcome array element
-
3639  # ifdef _OPENMP
-
3640  # pragma omp atomic update
-
3641  # endif
-
3642  outcomeProbs[outcomeInd] += stateRe[index];
-
3643  }
-
3644  }
-
3645 }
+
3618  // clear outcomeProbs (in parallel, in case it's large)
+
3619  long long int numOutcomeProbs = (1 << numQubits);
+
3620  long long int j;
+
3621 
+
3622 # ifdef _OPENMP
+
3623 # pragma omp parallel \
+
3624  default (none) \
+
3625  shared (numOutcomeProbs,outcomeProbs) \
+
3626  private (j)
+
3627 # endif
+
3628  {
+
3629 # ifdef _OPENMP
+
3630 # pragma omp for schedule (static)
+
3631 # endif
+
3632  for (j=0; j<numOutcomeProbs; j++)
+
3633  outcomeProbs[j] = 0;
+
3634  }
+
3635 
+
3636  // compute first local index containing a diagonal element
+
3637  long long int localNumAmps = qureg.numAmpsPerChunk;
+
3638  long long int densityDim = (1LL << qureg.numQubitsRepresented);
+
3639  long long int diagSpacing = 1LL + densityDim;
+
3640  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
+
3641  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
+
3642  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
3643  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
+
3644 
+
3645  // computes how many diagonals are contained in this chunk
+
3646  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
+
3647  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
+
3648  numDiagsInThisChunk -= 1;
+
3649 
+
3650  long long int visitedDiags; // number of visited diagonals in this chunk so far
+
3651  long long int basisStateInd; // current diagonal index being considered
+
3652  long long int index; // index in the local chunk
+
3653 
+
3654  int q;
+
3655  long long int outcomeInd;
+
3656  qreal *stateRe = qureg.stateVec.real;
+
3657 
+
3658 # ifdef _OPENMP
+
3659 # pragma omp parallel \
+
3660  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateRe, numDiagsInThisChunk, qubits,numQubits, outcomeProbs) \
+
3661  private (visitedDiags, basisStateInd, index, q,outcomeInd)
+
3662 # endif
+
3663  {
+
3664 # ifdef _OPENMP
+
3665 # pragma omp for schedule (static)
+
3666 # endif
+
3667  // sums the diagonal elems of the density matrix where measureQubit=0
+
3668  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
+
3669 
+
3670  basisStateInd = numPrevDiags + visitedDiags;
+
3671  index = localIndNextDiag + diagSpacing * visitedDiags;
+
3672 
+
3673  // determine outcome implied by basisStateInd
+
3674  outcomeInd = 0;
+
3675  for (q=0; q<numQubits; q++)
+
3676  outcomeInd += extractBit(qubits[q], basisStateInd) * (1LL << q);
+
3677 
+
3678  // atomicly update corresponding outcome array element
+
3679  # ifdef _OPENMP
+
3680  # pragma omp atomic
+
3681  # endif
+
3682  outcomeProbs[outcomeInd] += stateRe[index];
+
3683  }
+
3684  }
+
3685 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcProbOfAllOutcomes().

+

Referenced by densmatr_calcProbOfAllOutcomes().

@@ -1218,39 +1218,39 @@

-

Definition at line 861 of file QuEST_cpu.c.

-
861  {
-
862 
-
863  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
-
864  long long int index;
-
865  long long int numAmps = qureg.numAmpsPerChunk;
-
866 
-
867  qreal trace = 0;
-
868  qreal *vecRe = qureg.stateVec.real;
-
869  qreal *vecIm = qureg.stateVec.imag;
-
870 
-
871 # ifdef _OPENMP
-
872 # pragma omp parallel \
-
873  shared (vecRe, vecIm, numAmps) \
-
874  private (index) \
-
875  reduction ( +:trace )
-
876 # endif
-
877  {
-
878 # ifdef _OPENMP
-
879 # pragma omp for schedule (static)
-
880 # endif
-
881  for (index=0LL; index<numAmps; index++) {
-
882 
-
883  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
-
884  }
-
885  }
-
886 
-
887  return trace;
-
888 }
+

Definition at line 872 of file QuEST_cpu.c.

+
872  {
+
873 
+
874  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
+
875  long long int index;
+
876  long long int numAmps = qureg.numAmpsPerChunk;
+
877 
+
878  qreal trace = 0;
+
879  qreal *vecRe = qureg.stateVec.real;
+
880  qreal *vecIm = qureg.stateVec.imag;
+
881 
+
882 # ifdef _OPENMP
+
883 # pragma omp parallel \
+
884  shared (vecRe, vecIm, numAmps) \
+
885  private (index) \
+
886  reduction ( +:trace )
+
887 # endif
+
888  {
+
889 # ifdef _OPENMP
+
890 # pragma omp for schedule (static)
+
891 # endif
+
892  for (index=0LL; index<numAmps; index++) {
+
893 
+
894  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
+
895  }
+
896  }
+
897 
+
898  return trace;
+
899 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcPurity().

+

Referenced by densmatr_calcPurity().

@@ -1294,84 +1294,89 @@

Definition at line 785 of file QuEST_cpu.c.

-
785  {
-
786 
-
787  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
-
788  // where n = measureQubit, q = qureg.numQubitsRepresented.
-
789  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
-
790  // stepping in sub-blocks of 2^q, killing every second.
-
791  // When outcome=1, we offset the start of these blocks by their size.
-
792  long long int innerBlockSize = (1LL << measureQubit);
-
793  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
-
794 
-
795  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
-
796  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
-
797  long long int locNumAmps = qureg.numAmpsPerChunk;
-
798  long long int globalStartInd = qureg.chunkId * locNumAmps;
-
799  int innerBit = extractBit(measureQubit, globalStartInd);
-
800  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
-
801 
-
802  // If this chunk's amps are entirely inside an outer block
-
803  if (locNumAmps <= outerBlockSize) {
-
804 
-
805  // if this is an undesired outer block, kill all elems
-
806  if (outerBit != outcome)
-
807  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
808 
-
809  // othwerwise, if this is a desired outer block, and also entirely an inner block
-
810  if (locNumAmps <= innerBlockSize) {
-
811 
-
812  // and that inner block is undesired, kill all elems
-
813  if (innerBit != outcome)
-
814  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
815  // otherwise normalise all elems
-
816  else
-
817  return normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
-
818  }
-
819 
-
820  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
- -
822  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
-
823  }
-
824 
-
825  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
-
826  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
-
827  long long int firstBlockInd;
-
828 
-
829  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
-
830  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
-
831  // inner parallelisation
-
832  if (outerBit == outcome) {
-
833 
-
834  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
835  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
836 
-
837  // *norm only the desired inner blocks in the desired outer block
- -
839  qureg, totalStateProb, innerBit==outcome,
-
840  firstBlockInd, outerBlockSize, innerBlockSize);
-
841 
-
842  // zero the undesired outer block
-
843  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
-
844  }
-
845 
-
846  } else {
-
847 
-
848  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
849  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
850 
-
851  // same thing but undesired outer blocks come first
-
852  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
- -
854  qureg, totalStateProb, innerBit==outcome,
-
855  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
-
856  }
-
857  }
-
858 
-
859 }
+

Definition at line 791 of file QuEST_cpu.c.

+
791  {
+
792 
+
793  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
+
794  // where n = measureQubit, q = qureg.numQubitsRepresented.
+
795  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
+
796  // stepping in sub-blocks of 2^q, killing every second.
+
797  // When outcome=1, we offset the start of these blocks by their size.
+
798  long long int innerBlockSize = (1LL << measureQubit);
+
799  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
+
800 
+
801  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
+
802  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
+
803  long long int locNumAmps = qureg.numAmpsPerChunk;
+
804  long long int globalStartInd = qureg.chunkId * locNumAmps;
+
805  int innerBit = extractBit(measureQubit, globalStartInd);
+
806  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
+
807 
+
808  // If this chunk's amps are entirely inside an outer block
+
809  if (locNumAmps <= outerBlockSize) {
+
810 
+
811  // if this is an undesired outer block, kill all elems
+
812  if (outerBit != outcome) {
+
813  zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
+
814  return;
+
815  }
+
816 
+
817  // othwerwise, if this is a desired outer block, and also entirely an inner block
+
818  if (locNumAmps <= innerBlockSize) {
+
819 
+
820  // and that inner block is undesired, kill all elems
+
821  if (innerBit != outcome)
+
822  zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
+
823  // otherwise normalise all elems
+
824  else
+
825  normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
+
826 
+
827  return;
+
828  }
+
829 
+
830  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
+ +
832  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
+
833  return;
+
834  }
+
835 
+
836  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
+
837  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
+
838  long long int firstBlockInd;
+
839 
+
840  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
+
841  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
+
842  // inner parallelisation
+
843  if (outerBit == outcome) {
+
844 
+
845  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
+
846  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
+
847 
+
848  // *norm only the desired inner blocks in the desired outer block
+ +
850  qureg, totalStateProb, innerBit==outcome,
+
851  firstBlockInd, outerBlockSize, innerBlockSize);
+
852 
+
853  // zero the undesired outer block
+
854  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
+
855  }
+
856 
+
857  } else {
+
858 
+
859  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
+
860  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
+
861 
+
862  // same thing but undesired outer blocks come first
+
863  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
+ +
865  qureg, totalStateProb, innerBit==outcome,
+
866  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
+
867  }
+
868  }
+
869 
+
870 }
-

References alternateNormZeroingSomeAmpBlocks(), Qureg::chunkId, extractBit(), normaliseSomeAmps(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and zeroSomeAmps().

+

References alternateNormZeroingSomeAmpBlocks(), Qureg::chunkId, extractBit(), normaliseSomeAmps(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and zeroSomeAmps().

@@ -1401,58 +1406,58 @@

-

Definition at line 3363 of file QuEST_cpu.c.

-
3363  {
-
3364 
-
3365  // computes first local index containing a diagonal element
-
3366  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3367  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3368  long long int diagSpacing = 1LL + densityDim;
-
3369  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3370  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3371  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3372  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3373 
-
3374  // computes how many diagonals are contained in this chunk
-
3375  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3376  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3377  numDiagsInThisChunk -= 1;
-
3378 
-
3379  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3380  long long int basisStateInd; // current diagonal index being considered
-
3381  long long int index; // index in the local chunk
-
3382 
-
3383  qreal zeroProb = 0;
-
3384  qreal *stateVecReal = qureg.stateVec.real;
-
3385 
-
3386 # ifdef _OPENMP
-
3387 # pragma omp parallel \
-
3388  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
-
3389  private (visitedDiags, basisStateInd, index) \
-
3390  reduction ( +:zeroProb )
-
3391 # endif
-
3392  {
-
3393 # ifdef _OPENMP
-
3394 # pragma omp for schedule (static)
-
3395 # endif
-
3396  // sums the diagonal elems of the density matrix where measureQubit=0
-
3397  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3398 
-
3399  basisStateInd = numPrevDiags + visitedDiags;
-
3400  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3401 
-
3402  if (extractBit(measureQubit, basisStateInd) == 0)
-
3403  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
-
3404 
-
3405  }
-
3406  }
-
3407 
-
3408  return zeroProb;
-
3409 }
+

Definition at line 3402 of file QuEST_cpu.c.

+
3402  {
+
3403 
+
3404  // computes first local index containing a diagonal element
+
3405  long long int localNumAmps = qureg.numAmpsPerChunk;
+
3406  long long int densityDim = (1LL << qureg.numQubitsRepresented);
+
3407  long long int diagSpacing = 1LL + densityDim;
+
3408  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
+
3409  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
+
3410  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
3411  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
+
3412 
+
3413  // computes how many diagonals are contained in this chunk
+
3414  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
+
3415  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
+
3416  numDiagsInThisChunk -= 1;
+
3417 
+
3418  long long int visitedDiags; // number of visited diagonals in this chunk so far
+
3419  long long int basisStateInd; // current diagonal index being considered
+
3420  long long int index; // index in the local chunk
+
3421 
+
3422  qreal zeroProb = 0;
+
3423  qreal *stateVecReal = qureg.stateVec.real;
+
3424 
+
3425 # ifdef _OPENMP
+
3426 # pragma omp parallel \
+
3427  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
+
3428  private (visitedDiags, basisStateInd, index) \
+
3429  reduction ( +:zeroProb )
+
3430 # endif
+
3431  {
+
3432 # ifdef _OPENMP
+
3433 # pragma omp for schedule (static)
+
3434 # endif
+
3435  // sums the diagonal elems of the density matrix where measureQubit=0
+
3436  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
+
3437 
+
3438  basisStateInd = numPrevDiags + visitedDiags;
+
3439  index = localIndNextDiag + diagSpacing * visitedDiags;
+
3440 
+
3441  if (extractBit(measureQubit, basisStateInd) == 0)
+
3442  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
+
3443 
+
3444  }
+
3445  }
+
3446 
+
3447  return zeroProb;
+
3448 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcProbOfOutcome().

+

Referenced by densmatr_calcProbOfOutcome().

@@ -1482,43 +1487,43 @@

-

Definition at line 1115 of file QuEST_cpu.c.

-
1116 {
-
1117  // dimension of the state vector
-
1118  long long int densityNumElems = qureg.numAmpsPerChunk;
-
1119 
-
1120  // Can't use qureg->stateVec as a private OMP var
-
1121  qreal *densityReal = qureg.stateVec.real;
-
1122  qreal *densityImag = qureg.stateVec.imag;
-
1123 
-
1124  // initialise the state to all zeros
-
1125  long long int index;
-
1126 # ifdef _OPENMP
-
1127 # pragma omp parallel \
-
1128  default (none) \
-
1129  shared (densityNumElems, densityReal, densityImag) \
-
1130  private (index)
-
1131 # endif
-
1132  {
-
1133 # ifdef _OPENMP
-
1134 # pragma omp for schedule (static)
-
1135 # endif
-
1136  for (index=0; index<densityNumElems; index++) {
-
1137  densityReal[index] = 0.0;
-
1138  densityImag[index] = 0.0;
-
1139  }
-
1140  }
-
1141 
-
1142  // index of the single density matrix elem to set non-zero
-
1143  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1144  long long int densityInd = (densityDim + 1)*stateInd;
-
1145 
-
1146  // give the specified classical state prob 1
-
1147  if (qureg.chunkId == densityInd / densityNumElems){
-
1148  densityReal[densityInd % densityNumElems] = 1.0;
-
1149  densityImag[densityInd % densityNumElems] = 0.0;
-
1150  }
-
1151 }
+

Definition at line 1126 of file QuEST_cpu.c.

+
1127 {
+
1128  // dimension of the state vector
+
1129  long long int densityNumElems = qureg.numAmpsPerChunk;
+
1130 
+
1131  // Can't use qureg->stateVec as a private OMP var
+
1132  qreal *densityReal = qureg.stateVec.real;
+
1133  qreal *densityImag = qureg.stateVec.imag;
+
1134 
+
1135  // initialise the state to all zeros
+
1136  long long int index;
+
1137 # ifdef _OPENMP
+
1138 # pragma omp parallel \
+
1139  default (none) \
+
1140  shared (densityNumElems, densityReal, densityImag) \
+
1141  private (index)
+
1142 # endif
+
1143  {
+
1144 # ifdef _OPENMP
+
1145 # pragma omp for schedule (static)
+
1146 # endif
+
1147  for (index=0; index<densityNumElems; index++) {
+
1148  densityReal[index] = 0.0;
+
1149  densityImag[index] = 0.0;
+
1150  }
+
1151  }
+
1152 
+
1153  // index of the single density matrix elem to set non-zero
+
1154  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
1155  long long int densityInd = (densityDim + 1)*stateInd;
+
1156 
+
1157  // give the specified classical state prob 1
+
1158  if (qureg.chunkId == densityInd / densityNumElems){
+
1159  densityReal[densityInd % densityNumElems] = 1.0;
+
1160  densityImag[densityInd % densityNumElems] = 0.0;
+
1161  }
+
1162 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

@@ -1540,35 +1545,35 @@

-

Definition at line 1154 of file QuEST_cpu.c.

-
1155 {
-
1156  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
-
1157  long long int dim = (1LL << qureg.numQubitsRepresented);
-
1158  qreal probFactor = 1.0/((qreal) dim);
-
1159 
-
1160  // Can't use qureg->stateVec as a private OMP var
-
1161  qreal *densityReal = qureg.stateVec.real;
-
1162  qreal *densityImag = qureg.stateVec.imag;
-
1163 
-
1164  long long int index;
-
1165  long long int chunkSize = qureg.numAmpsPerChunk;
-
1166  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1167 # ifdef _OPENMP
-
1168 # pragma omp parallel \
-
1169  default (none) \
-
1170  shared (chunkSize, densityReal, densityImag, probFactor) \
-
1171  private (index)
-
1172 # endif
-
1173  {
-
1174 # ifdef _OPENMP
-
1175 # pragma omp for schedule (static)
-
1176 # endif
-
1177  for (index=0; index<chunkSize; index++) {
-
1178  densityReal[index] = probFactor;
-
1179  densityImag[index] = 0.0;
-
1180  }
-
1181  }
-
1182 }
+

Definition at line 1165 of file QuEST_cpu.c.

+
1166 {
+
1167  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
+
1168  long long int dim = (1LL << qureg.numQubitsRepresented);
+
1169  qreal probFactor = 1.0/((qreal) dim);
+
1170 
+
1171  // Can't use qureg->stateVec as a private OMP var
+
1172  qreal *densityReal = qureg.stateVec.real;
+
1173  qreal *densityImag = qureg.stateVec.imag;
+
1174 
+
1175  long long int index;
+
1176  long long int chunkSize = qureg.numAmpsPerChunk;
+
1177  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
+
1178 # ifdef _OPENMP
+
1179 # pragma omp parallel \
+
1180  default (none) \
+
1181  shared (chunkSize, densityReal, densityImag, probFactor) \
+
1182  private (index)
+
1183 # endif
+
1184  {
+
1185 # ifdef _OPENMP
+
1186 # pragma omp for schedule (static)
+
1187 # endif
+
1188  for (index=0; index<chunkSize; index++) {
+
1189  densityReal[index] = probFactor;
+
1190  densityImag[index] = 0.0;
+
1191  }
+
1192  }
+
1193 }

References Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

@@ -1600,63 +1605,63 @@

-

Definition at line 1184 of file QuEST_cpu.c.

-
1184  {
-
1185 
-
1186  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
-
1187  * which contains the full pure statevector.
-
1188  * targetQureg has as many columns on node as copyQureg has amps
-
1189  */
-
1190 
-
1191  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
-
1192  long long int colsPerNode = copyQureg.numAmpsPerChunk;
-
1193  long long int rowsPerNode = copyQureg.numAmpsTotal;
-
1194 
-
1195  // unpack vars for OpenMP
-
1196  qreal* vecRe = targetQureg.pairStateVec.real;
-
1197  qreal* vecIm = targetQureg.pairStateVec.imag;
-
1198  qreal* densRe = targetQureg.stateVec.real;
-
1199  qreal* densIm = targetQureg.stateVec.imag;
-
1200 
-
1201  long long int col, row, index;
-
1202 
-
1203  // a_i conj(a_j) |i><j|
-
1204  qreal ketRe, ketIm, braRe, braIm;
+

Definition at line 1195 of file QuEST_cpu.c.

+
1195  {
+
1196 
+
1197  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
+
1198  * which contains the full pure statevector.
+
1199  * targetQureg has as many columns on node as copyQureg has amps
+
1200  */
+
1201 
+
1202  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
+
1203  long long int colsPerNode = copyQureg.numAmpsPerChunk;
+
1204  long long int rowsPerNode = copyQureg.numAmpsTotal;
1205 
-
1206 # ifdef _OPENMP
-
1207 # pragma omp parallel \
-
1208  default (none) \
-
1209  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
-
1210  private (col,row, ketRe,ketIm,braRe,braIm, index)
-
1211 # endif
-
1212  {
-
1213 # ifdef _OPENMP
-
1214 # pragma omp for schedule (static)
-
1215 # endif
-
1216  // local column
-
1217  for (col=0; col < colsPerNode; col++) {
-
1218 
-
1219  // global row
-
1220  for (row=0; row < rowsPerNode; row++) {
-
1221 
-
1222  // get pure state amps
-
1223  ketRe = vecRe[row];
-
1224  ketIm = vecIm[row];
-
1225  braRe = vecRe[col + colOffset];
-
1226  braIm = - vecIm[col + colOffset]; // minus for conjugation
-
1227 
-
1228  // update density matrix
-
1229  index = row + col*rowsPerNode; // local ind
-
1230  densRe[index] = ketRe*braRe - ketIm*braIm;
-
1231  densIm[index] = ketRe*braIm + ketIm*braRe;
-
1232  }
-
1233  }
-
1234  }
-
1235 }
+
1206  // unpack vars for OpenMP
+
1207  qreal* vecRe = targetQureg.pairStateVec.real;
+
1208  qreal* vecIm = targetQureg.pairStateVec.imag;
+
1209  qreal* densRe = targetQureg.stateVec.real;
+
1210  qreal* densIm = targetQureg.stateVec.imag;
+
1211 
+
1212  long long int col, row, index;
+
1213 
+
1214  // a_i conj(a_j) |i><j|
+
1215  qreal ketRe, ketIm, braRe, braIm;
+
1216 
+
1217 # ifdef _OPENMP
+
1218 # pragma omp parallel \
+
1219  default (none) \
+
1220  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
+
1221  private (col,row, ketRe,ketIm,braRe,braIm, index)
+
1222 # endif
+
1223  {
+
1224 # ifdef _OPENMP
+
1225 # pragma omp for schedule (static)
+
1226 # endif
+
1227  // local column
+
1228  for (col=0; col < colsPerNode; col++) {
+
1229 
+
1230  // global row
+
1231  for (row=0; row < rowsPerNode; row++) {
+
1232 
+
1233  // get pure state amps
+
1234  ketRe = vecRe[row];
+
1235  ketIm = vecIm[row];
+
1236  braRe = vecRe[col + colOffset];
+
1237  braIm = - vecIm[col + colOffset]; // minus for conjugation
+
1238 
+
1239  // update density matrix
+
1240  index = row + col*rowsPerNode; // local ind
+
1241  densRe[index] = ketRe*braRe - ketIm*braIm;
+
1242  densIm[index] = ketRe*braIm + ketIm*braRe;
+
1243  }
+
1244  }
+
1245  }
+
1246 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_initPureState().

+

Referenced by densmatr_initPureState().

@@ -1692,97 +1697,97 @@

-

Definition at line 300 of file QuEST_cpu.c.

-
300  {
-
301  qreal retain=1-damping;
-
302  qreal dephase=sqrt(1-damping);
-
303 
-
304  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
-
305  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
306 
-
307  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
-
308 
-
309  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
310  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
311  long long int thisInnerBlock, // current block
-
312  thisOuterColumn, // current column in density matrix
-
313  thisIndex, // current index in (density matrix representation) state vector
-
314  thisIndexInOuterColumn,
-
315  thisIndexInInnerBlock;
-
316  int outerBit;
-
317  int stateBit;
-
318 
-
319  long long int thisTask;
-
320  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
321 
-
322  // set dimensions
-
323  sizeInnerHalfBlock = 1LL << targetQubit;
-
324  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
325  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
326  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+

Definition at line 306 of file QuEST_cpu.c.

+
306  {
+
307  qreal retain=1-damping;
+
308  qreal dephase=sqrt(1-damping);
+
309 
+
310  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
+
311  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
+
312 
+
313  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
+
314 
+
315  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
316  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
317  long long int thisInnerBlock, // current block
+
318  thisOuterColumn, // current column in density matrix
+
319  thisIndex, // current index in (density matrix representation) state vector
+
320  thisIndexInOuterColumn,
+
321  thisIndexInInnerBlock;
+
322  int outerBit;
+
323  int stateBit;
+
324 
+
325  long long int thisTask;
+
326  long long int numTasks=qureg.numAmpsPerChunk>>1;
327 
-
328 # ifdef _OPENMP
-
329 # pragma omp parallel \
-
330  default (none) \
-
331  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
332  qureg,damping, retain, dephase, numTasks,targetQubit) \
-
333  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
334  thisIndexInInnerBlock,outerBit, stateBit)
-
335 # endif
-
336  {
-
337 # ifdef _OPENMP
-
338 # pragma omp for schedule (static)
-
339 # endif
-
340  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
341  // treat this as iterating over all columns, then iterating over half the values
-
342  // within one column.
-
343  // If this function has been called, this process' chunk contains half an
-
344  // outer block or less
-
345  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
346  // we want to process all columns in the density matrix,
-
347  // updating the values for half of each column (one half of each inner block)
-
348  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
349  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
350  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
351  // get index in state vector corresponding to upper inner block
-
352  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
353  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
354  + thisIndexInInnerBlock;
-
355  // check if we are in the upper or lower half of an outer block
-
356  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
357  // if we are in the lower half of an outer block, shift to be in the lower half
-
358  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
359  thisIndex += outerBit*(sizeInnerHalfBlock);
-
360 
-
361  // NOTE: at this point thisIndex should be the index of the element we want to
-
362  // dephase in the chunk of the state vector on this process, in the
-
363  // density matrix representation.
-
364  // thisTask is the index of the pair element in pairStateVec
-
365 
-
366  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
-
367  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
-
368  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
-
369 
-
370  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
371  // + pair[thisTask])/2
-
372  if(stateBit == 0){
-
373  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
-
374  damping*( qureg.pairStateVec.real[thisTask]);
-
375 
-
376  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
-
377  damping*( qureg.pairStateVec.imag[thisTask]);
-
378  } else{
-
379  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
-
380 
-
381  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
-
382  }
-
383  }
-
384  }
-
385 }
+
328  // set dimensions
+
329  sizeInnerHalfBlock = 1LL << targetQubit;
+
330  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
331  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
332  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
333 
+
334 # ifdef _OPENMP
+
335 # pragma omp parallel \
+
336  default (none) \
+
337  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
338  qureg,damping, retain, dephase, numTasks,targetQubit) \
+
339  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
340  thisIndexInInnerBlock,outerBit, stateBit)
+
341 # endif
+
342  {
+
343 # ifdef _OPENMP
+
344 # pragma omp for schedule (static)
+
345 # endif
+
346  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
347  // treat this as iterating over all columns, then iterating over half the values
+
348  // within one column.
+
349  // If this function has been called, this process' chunk contains half an
+
350  // outer block or less
+
351  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
352  // we want to process all columns in the density matrix,
+
353  // updating the values for half of each column (one half of each inner block)
+
354  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
355  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
356  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
357  // get index in state vector corresponding to upper inner block
+
358  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
359  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
360  + thisIndexInInnerBlock;
+
361  // check if we are in the upper or lower half of an outer block
+
362  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
363  // if we are in the lower half of an outer block, shift to be in the lower half
+
364  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
365  thisIndex += outerBit*(sizeInnerHalfBlock);
+
366 
+
367  // NOTE: at this point thisIndex should be the index of the element we want to
+
368  // dephase in the chunk of the state vector on this process, in the
+
369  // density matrix representation.
+
370  // thisTask is the index of the pair element in pairStateVec
+
371 
+
372  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
+
373  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
+
374  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
+
375 
+
376  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
377  // + pair[thisTask])/2
+
378  if(stateBit == 0){
+
379  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
+
380  damping*( qureg.pairStateVec.real[thisTask]);
+
381 
+
382  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
+
383  damping*( qureg.pairStateVec.imag[thisTask]);
+
384  } else{
+
385  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
+
386 
+
387  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
+
388  }
+
389  }
+
390  }
+
391 }
-

References Qureg::chunkId, densmatr_oneQubitDegradeOffDiagonal(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, densmatr_oneQubitDegradeOffDiagonal(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixDamping().

+

Referenced by densmatr_mixDamping().

@@ -1818,60 +1823,60 @@

-

Definition at line 174 of file QuEST_cpu.c.

-
174  {
-
175  qreal retain=1-damping;
-
176  qreal dephase=sqrt(retain);
-
177 
-
178  long long int numTasks = qureg.numAmpsPerChunk;
-
179  long long int innerMask = 1LL << targetQubit;
-
180  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
181  long long int totMask = innerMask|outerMask;
-
182 
-
183  long long int thisTask;
-
184  long long int partner;
-
185  long long int thisPattern;
-
186 
-
187  //qreal realAv, imagAv;
-
188 
-
189 # ifdef _OPENMP
-
190 # pragma omp parallel \
-
191  default (none) \
-
192  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
-
193  private (thisTask,partner,thisPattern)
-
194 # endif
-
195  {
-
196 # ifdef _OPENMP
-
197 # pragma omp for schedule (static)
-
198 # endif
-
199  for (thisTask=0; thisTask<numTasks; thisTask++){
-
200  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
201  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
202  // do dephase
-
203  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
204  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
-
205  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
-
206  } else {
-
207  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
208  // do depolarise
-
209  partner = thisTask | totMask;
-
210  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
211  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
212 
-
213  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
-
214  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
-
215 
-
216  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
-
217  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
-
218  }
-
219  }
-
220  }
-
221  }
-
222 }
+

Definition at line 180 of file QuEST_cpu.c.

+
180  {
+
181  qreal retain=1-damping;
+
182  qreal dephase=sqrt(retain);
+
183 
+
184  long long int numTasks = qureg.numAmpsPerChunk;
+
185  long long int innerMask = 1LL << targetQubit;
+
186  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
187  long long int totMask = innerMask|outerMask;
+
188 
+
189  long long int thisTask;
+
190  long long int partner;
+
191  long long int thisPattern;
+
192 
+
193  //qreal realAv, imagAv;
+
194 
+
195 # ifdef _OPENMP
+
196 # pragma omp parallel \
+
197  default (none) \
+
198  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
+
199  private (thisTask,partner,thisPattern)
+
200 # endif
+
201  {
+
202 # ifdef _OPENMP
+
203 # pragma omp for schedule (static)
+
204 # endif
+
205  for (thisTask=0; thisTask<numTasks; thisTask++){
+
206  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
207  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
208  // do dephase
+
209  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
210  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
+
211  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
+
212  } else {
+
213  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
+
214  // do depolarise
+
215  partner = thisTask | totMask;
+
216  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
+
217  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
+
218 
+
219  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
+
220  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
+
221 
+
222  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
+
223  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
+
224  }
+
225  }
+
226  }
+
227  }
+
228 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixDamping().

+

Referenced by densmatr_mixDamping().

@@ -1907,38 +1912,38 @@

-

Definition at line 890 of file QuEST_cpu.c.

-
890  {
-
891 
-
892  /* corresponding amplitudes live on the same node (same dimensions) */
-
893 
-
894  // unpack vars for OpenMP
-
895  qreal* combineVecRe = combineQureg.stateVec.real;
-
896  qreal* combineVecIm = combineQureg.stateVec.imag;
-
897  qreal* otherVecRe = otherQureg.stateVec.real;
-
898  qreal* otherVecIm = otherQureg.stateVec.imag;
-
899  long long int numAmps = combineQureg.numAmpsPerChunk;
-
900  long long int index;
-
901 
-
902 # ifdef _OPENMP
-
903 # pragma omp parallel \
-
904  default (none) \
-
905  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
-
906  private (index)
-
907 # endif
-
908  {
-
909 # ifdef _OPENMP
-
910 # pragma omp for schedule (static)
-
911 # endif
-
912  for (index=0; index < numAmps; index++) {
-
913  combineVecRe[index] *= 1-otherProb;
-
914  combineVecIm[index] *= 1-otherProb;
-
915 
-
916  combineVecRe[index] += otherProb * otherVecRe[index];
-
917  combineVecIm[index] += otherProb * otherVecIm[index];
-
918  }
-
919  }
-
920 }
+

Definition at line 901 of file QuEST_cpu.c.

+
901  {
+
902 
+
903  /* corresponding amplitudes live on the same node (same dimensions) */
+
904 
+
905  // unpack vars for OpenMP
+
906  qreal* combineVecRe = combineQureg.stateVec.real;
+
907  qreal* combineVecIm = combineQureg.stateVec.imag;
+
908  qreal* otherVecRe = otherQureg.stateVec.real;
+
909  qreal* otherVecIm = otherQureg.stateVec.imag;
+
910  long long int numAmps = combineQureg.numAmpsPerChunk;
+
911  long long int index;
+
912 
+
913 # ifdef _OPENMP
+
914 # pragma omp parallel \
+
915  default (none) \
+
916  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
+
917  private (index)
+
918 # endif
+
919  {
+
920 # ifdef _OPENMP
+
921 # pragma omp for schedule (static)
+
922 # endif
+
923  for (index=0; index < numAmps; index++) {
+
924  combineVecRe[index] *= 1-otherProb;
+
925  combineVecIm[index] *= 1-otherProb;
+
926 
+
927  combineVecRe[index] += otherProb * otherVecRe[index];
+
928  combineVecIm[index] += otherProb * otherVecIm[index];
+
929  }
+
930  }
+
931 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -1976,15 +1981,15 @@

-

Definition at line 79 of file QuEST_cpu.c.

-
79  {
-
80  qreal retain=1-dephase;
-
81  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
-
82 }
+

Definition at line 85 of file QuEST_cpu.c.

+
85  {
+
86  qreal retain=1-dephase;
+
87  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
+
88 }
-

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

+

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

-

Referenced by densmatr_mixDepolarisingDistributed().

+

Referenced by densmatr_mixDepolarisingDistributed().

@@ -2020,86 +2025,86 @@

-

Definition at line 224 of file QuEST_cpu.c.

-
224  {
-
225 
-
226  // first do dephase part.
-
227  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
-
228  // iterating over all elements in the state vector for the purpose of vectorisation
-
229  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
-
230  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+

Definition at line 230 of file QuEST_cpu.c.

+
230  {
231 
-
232  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
233  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
234  long long int thisInnerBlock, // current block
-
235  thisOuterColumn, // current column in density matrix
-
236  thisIndex, // current index in (density matrix representation) state vector
-
237  thisIndexInOuterColumn,
-
238  thisIndexInInnerBlock;
-
239  int outerBit;
-
240 
-
241  long long int thisTask;
-
242  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
243 
-
244  // set dimensions
-
245  sizeInnerHalfBlock = 1LL << targetQubit;
-
246  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
247  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
248  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
232  // first do dephase part.
+
233  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
+
234  // iterating over all elements in the state vector for the purpose of vectorisation
+
235  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
+
236  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
237 
+
238  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
239  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
240  long long int thisInnerBlock, // current block
+
241  thisOuterColumn, // current column in density matrix
+
242  thisIndex, // current index in (density matrix representation) state vector
+
243  thisIndexInOuterColumn,
+
244  thisIndexInInnerBlock;
+
245  int outerBit;
+
246 
+
247  long long int thisTask;
+
248  long long int numTasks=qureg.numAmpsPerChunk>>1;
249 
-
250 # ifdef _OPENMP
-
251 # pragma omp parallel \
-
252  default (none) \
-
253  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
254  qureg,depolLevel,numTasks,targetQubit) \
-
255  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
256  thisIndexInInnerBlock,outerBit)
-
257 # endif
-
258  {
-
259 # ifdef _OPENMP
-
260 # pragma omp for schedule (static)
-
261 # endif
-
262  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
263  // treat this as iterating over all columns, then iterating over half the values
-
264  // within one column.
-
265  // If this function has been called, this process' chunk contains half an
-
266  // outer block or less
-
267  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
268  // we want to process all columns in the density matrix,
-
269  // updating the values for half of each column (one half of each inner block)
-
270  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
271  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
272  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
273  // get index in state vector corresponding to upper inner block
-
274  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
275  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
276  + thisIndexInInnerBlock;
-
277  // check if we are in the upper or lower half of an outer block
-
278  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
279  // if we are in the lower half of an outer block, shift to be in the lower half
-
280  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
281  thisIndex += outerBit*(sizeInnerHalfBlock);
-
282 
-
283  // NOTE: at this point thisIndex should be the index of the element we want to
-
284  // dephase in the chunk of the state vector on this process, in the
-
285  // density matrix representation.
-
286  // thisTask is the index of the pair element in pairStateVec
-
287 
-
288 
-
289  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
290  // + pair[thisTask])/2
-
291  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
-
292  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
-
293 
-
294  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
-
295  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
-
296  }
-
297  }
-
298 }
+
250  // set dimensions
+
251  sizeInnerHalfBlock = 1LL << targetQubit;
+
252  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
253  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
254  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
255 
+
256 # ifdef _OPENMP
+
257 # pragma omp parallel \
+
258  default (none) \
+
259  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
260  qureg,depolLevel,numTasks,targetQubit) \
+
261  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
262  thisIndexInInnerBlock,outerBit)
+
263 # endif
+
264  {
+
265 # ifdef _OPENMP
+
266 # pragma omp for schedule (static)
+
267 # endif
+
268  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
269  // treat this as iterating over all columns, then iterating over half the values
+
270  // within one column.
+
271  // If this function has been called, this process' chunk contains half an
+
272  // outer block or less
+
273  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
274  // we want to process all columns in the density matrix,
+
275  // updating the values for half of each column (one half of each inner block)
+
276  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
277  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
278  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
279  // get index in state vector corresponding to upper inner block
+
280  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
281  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
282  + thisIndexInInnerBlock;
+
283  // check if we are in the upper or lower half of an outer block
+
284  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
285  // if we are in the lower half of an outer block, shift to be in the lower half
+
286  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
287  thisIndex += outerBit*(sizeInnerHalfBlock);
+
288 
+
289  // NOTE: at this point thisIndex should be the index of the element we want to
+
290  // dephase in the chunk of the state vector on this process, in the
+
291  // density matrix representation.
+
292  // thisTask is the index of the pair element in pairStateVec
+
293 
+
294 
+
295  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
296  // + pair[thisTask])/2
+
297  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
+
298  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
+
299 
+
300  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
+
301  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
+
302  }
+
303  }
+
304 }
-

References Qureg::chunkId, densmatr_mixDephasing(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

+

References Qureg::chunkId, densmatr_mixDephasing(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixDepolarising().

+

Referenced by densmatr_mixDepolarising().

@@ -2135,59 +2140,59 @@

-

Definition at line 125 of file QuEST_cpu.c.

-
125  {
-
126  qreal retain=1-depolLevel;
-
127 
-
128  long long int numTasks = qureg.numAmpsPerChunk;
-
129  long long int innerMask = 1LL << targetQubit;
-
130  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
131  long long int totMask = innerMask|outerMask;
-
132 
-
133  long long int thisTask;
-
134  long long int partner;
-
135  long long int thisPattern;
-
136 
-
137  qreal realAv, imagAv;
-
138 
-
139 # ifdef _OPENMP
-
140 # pragma omp parallel \
-
141  default (none) \
-
142  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
-
143  private (thisTask,partner,thisPattern,realAv,imagAv)
-
144 # endif
-
145  {
-
146 # ifdef _OPENMP
-
147 # pragma omp for schedule (static)
-
148 # endif
-
149  for (thisTask=0; thisTask<numTasks; thisTask++){
-
150  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
151  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
152  // do dephase
-
153  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
154  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
155  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
156  } else {
-
157  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
158  // do depolarise
-
159  partner = thisTask | totMask;
-
160  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
161  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
162 
-
163  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
-
164  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
-
165 
-
166  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
-
167  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
-
168  }
-
169  }
-
170  }
-
171  }
-
172 }
+

Definition at line 131 of file QuEST_cpu.c.

+
131  {
+
132  qreal retain=1-depolLevel;
+
133 
+
134  long long int numTasks = qureg.numAmpsPerChunk;
+
135  long long int innerMask = 1LL << targetQubit;
+
136  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
137  long long int totMask = innerMask|outerMask;
+
138 
+
139  long long int thisTask;
+
140  long long int partner;
+
141  long long int thisPattern;
+
142 
+
143  qreal realAv, imagAv;
+
144 
+
145 # ifdef _OPENMP
+
146 # pragma omp parallel \
+
147  default (none) \
+
148  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
+
149  private (thisTask,partner,thisPattern,realAv,imagAv)
+
150 # endif
+
151  {
+
152 # ifdef _OPENMP
+
153 # pragma omp for schedule (static)
+
154 # endif
+
155  for (thisTask=0; thisTask<numTasks; thisTask++){
+
156  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
157  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
158  // do dephase
+
159  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
160  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
161  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
162  } else {
+
163  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
+
164  // do depolarise
+
165  partner = thisTask | totMask;
+
166  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
+
167  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
+
168 
+
169  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
+
170  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
+
171 
+
172  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
+
173  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
+
174  }
+
175  }
+
176  }
+
177  }
+
178 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixDepolarising().

+

Referenced by densmatr_mixDepolarising().

@@ -2229,47 +2234,47 @@

-

Definition at line 84 of file QuEST_cpu.c.

-
84  {
-
85  qreal retain=1-dephase;
-
86 
-
87  long long int numTasks = qureg.numAmpsPerChunk;
-
88  long long int innerMaskQubit1 = 1LL << qubit1;
-
89  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
-
90  long long int innerMaskQubit2 = 1LL << qubit2;
-
91  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
-
92  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
-
93  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
-
94 
-
95  long long int thisTask;
-
96  long long int thisPatternQubit1, thisPatternQubit2;
-
97 
-
98 # ifdef _OPENMP
-
99 # pragma omp parallel \
-
100  default (none) \
-
101  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
-
102  totMaskQubit2,qureg,retain,numTasks) \
-
103  private (thisTask,thisPatternQubit1,thisPatternQubit2)
-
104 # endif
-
105  {
-
106 # ifdef _OPENMP
-
107 # pragma omp for schedule (static)
-
108 # endif
-
109  for (thisTask=0; thisTask<numTasks; thisTask++){
-
110  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
111  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
112 
-
113  // any mismatch |...0...><...1...| etc
-
114  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
-
115  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
-
116  // do dephase
-
117  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
118  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
119  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
120  }
-
121  }
-
122  }
-
123 }
+

Definition at line 90 of file QuEST_cpu.c.

+
90  {
+
91  qreal retain=1-dephase;
+
92 
+
93  long long int numTasks = qureg.numAmpsPerChunk;
+
94  long long int innerMaskQubit1 = 1LL << qubit1;
+
95  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
+
96  long long int innerMaskQubit2 = 1LL << qubit2;
+
97  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
+
98  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
+
99  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
+
100 
+
101  long long int thisTask;
+
102  long long int thisPatternQubit1, thisPatternQubit2;
+
103 
+
104 # ifdef _OPENMP
+
105 # pragma omp parallel \
+
106  default (none) \
+
107  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
+
108  totMaskQubit2,qureg,retain,numTasks) \
+
109  private (thisTask,thisPatternQubit1,thisPatternQubit2)
+
110 # endif
+
111  {
+
112 # ifdef _OPENMP
+
113 # pragma omp for schedule (static)
+
114 # endif
+
115  for (thisTask=0; thisTask<numTasks; thisTask++){
+
116  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
117  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
118 
+
119  // any mismatch |...0...><...1...| etc
+
120  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
+
121  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
+
122  // do dephase
+
123  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
124  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
125  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
126  }
+
127  }
+
128  }
+
129 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

@@ -2319,100 +2324,100 @@

-

Definition at line 541 of file QuEST_cpu.c.

-
542  {
-
543 
-
544  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
545  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
546  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
547  long long int thisInnerBlockQ2,
-
548  thisOuterColumn, // current column in density matrix
-
549  thisIndex, // current index in (density matrix representation) state vector
-
550  thisIndexInOuterColumn,
-
551  thisIndexInInnerBlockQ1,
-
552  thisIndexInInnerBlockQ2,
-
553  thisInnerBlockQ1InInnerBlockQ2;
-
554  int outerBitQ1, outerBitQ2;
-
555 
-
556  long long int thisTask;
-
557  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
558 
-
559  // set dimensions
-
560  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
561  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
562  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
563  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
564  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
565  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
566  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
567 
-
568 # ifdef _OPENMP
-
569 # pragma omp parallel \
-
570  default (none) \
-
571  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
572  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
-
573  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
574  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
575  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
576 # endif
-
577  {
-
578 # ifdef _OPENMP
-
579 # pragma omp for schedule (static)
-
580 # endif
-
581  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
582  // treat this as iterating over all columns, then iterating over half the values
-
583  // within one column.
-
584  // If this function has been called, this process' chunk contains half an
-
585  // outer block or less
-
586  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
587  // we want to process all columns in the density matrix,
-
588  // updating the values for half of each column (one half of each inner block)
-
589  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
590  // thisTask % sizeOuterQuarterColumn
-
591  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
592  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
593  // thisTask % sizeInnerQuarterBlockQ2;
-
594  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
595  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
596  // thisTask % sizeInnerHalfBlockQ1;
-
597  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
598 
-
599  // get index in state vector corresponding to upper inner block
-
600  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
601  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
602 
-
603  // check if we are in the upper or lower half of an outer block for Q1
-
604  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
605  // if we are in the lower half of an outer block, shift to be in the lower half
-
606  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
607  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+

Definition at line 547 of file QuEST_cpu.c.

+
548  {
+
549 
+
550  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
551  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
552  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
553  long long int thisInnerBlockQ2,
+
554  thisOuterColumn, // current column in density matrix
+
555  thisIndex, // current index in (density matrix representation) state vector
+
556  thisIndexInOuterColumn,
+
557  thisIndexInInnerBlockQ1,
+
558  thisIndexInInnerBlockQ2,
+
559  thisInnerBlockQ1InInnerBlockQ2;
+
560  int outerBitQ1, outerBitQ2;
+
561 
+
562  long long int thisTask;
+
563  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
564 
+
565  // set dimensions
+
566  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
567  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
568  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
569  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
570  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
571  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
572  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
573 
+
574 # ifdef _OPENMP
+
575 # pragma omp parallel \
+
576  default (none) \
+
577  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
+
578  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
+
579  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
+
580  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
581  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
+
582 # endif
+
583  {
+
584 # ifdef _OPENMP
+
585 # pragma omp for schedule (static)
+
586 # endif
+
587  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
588  // treat this as iterating over all columns, then iterating over half the values
+
589  // within one column.
+
590  // If this function has been called, this process' chunk contains half an
+
591  // outer block or less
+
592  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
593  // we want to process all columns in the density matrix,
+
594  // updating the values for half of each column (one half of each inner block)
+
595  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
596  // thisTask % sizeOuterQuarterColumn
+
597  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
598  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
599  // thisTask % sizeInnerQuarterBlockQ2;
+
600  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
601  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
602  // thisTask % sizeInnerHalfBlockQ1;
+
603  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
+
604 
+
605  // get index in state vector corresponding to upper inner block
+
606  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
607  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
608 
-
609  // check if we are in the upper or lower half of an outer block for Q2
-
610  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
609  // check if we are in the upper or lower half of an outer block for Q1
+
610  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
611  // if we are in the lower half of an outer block, shift to be in the lower half
612  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
613  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
613  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
614 
-
615  // NOTE: at this point thisIndex should be the index of the element we want to
-
616  // dephase in the chunk of the state vector on this process, in the
-
617  // density matrix representation.
-
618  // thisTask is the index of the pair element in pairStateVec
-
619 
-
620 
-
621  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
622  // + pair[thisTask])/2
-
623  // NOTE: must set gamma=1 if using this function for steps 1 or 2
-
624  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
625  delta*qureg.pairStateVec.real[thisTask]);
-
626  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
627  delta*qureg.pairStateVec.imag[thisTask]);
-
628  }
-
629  }
-
630 }
+
615  // check if we are in the upper or lower half of an outer block for Q2
+
616  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
617  // if we are in the lower half of an outer block, shift to be in the lower half
+
618  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
619  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
620 
+
621  // NOTE: at this point thisIndex should be the index of the element we want to
+
622  // dephase in the chunk of the state vector on this process, in the
+
623  // density matrix representation.
+
624  // thisTask is the index of the pair element in pairStateVec
+
625 
+
626 
+
627  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
628  // + pair[thisTask])/2
+
629  // NOTE: must set gamma=1 if using this function for steps 1 or 2
+
630  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
+
631  delta*qureg.pairStateVec.real[thisTask]);
+
632  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
+
633  delta*qureg.pairStateVec.imag[thisTask]);
+
634  }
+
635  }
+
636 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -2460,111 +2465,111 @@

-

Definition at line 387 of file QuEST_cpu.c.

-
387  {
-
388  long long int numTasks = qureg.numAmpsPerChunk;
-
389  long long int innerMaskQubit1 = 1LL << qubit1;
-
390  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
391  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
392  long long int innerMaskQubit2 = 1LL << qubit2;
-
393  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
394  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
395 
-
396  long long int thisTask;
-
397  long long int partner;
-
398  long long int thisPatternQubit1, thisPatternQubit2;
-
399 
-
400  qreal real00, imag00;
+

Definition at line 393 of file QuEST_cpu.c.

+
393  {
+
394  long long int numTasks = qureg.numAmpsPerChunk;
+
395  long long int innerMaskQubit1 = 1LL << qubit1;
+
396  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
+
397  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
+
398  long long int innerMaskQubit2 = 1LL << qubit2;
+
399  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
+
400  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
401 
-
402 # ifdef _OPENMP
-
403 # pragma omp parallel \
-
404  default (none) \
-
405  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
-
406  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
407 # endif
-
408  {
-
409 # ifdef _OPENMP
-
410 # pragma omp for schedule (static)
-
411 # endif
-
412  //--------------------------------------- STEP ONE ---------------------
-
413  for (thisTask=0; thisTask<numTasks; thisTask++){
-
414  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
415  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
416  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
417  || (thisPatternQubit2==totMaskQubit2))){
-
418  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
419  partner = thisTask | totMaskQubit1;
-
420  real00 = qureg.stateVec.real[thisTask];
-
421  imag00 = qureg.stateVec.imag[thisTask];
-
422 
-
423  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
424  + delta*qureg.stateVec.real[partner];
-
425  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
426  + delta*qureg.stateVec.imag[partner];
-
427 
-
428  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
429  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
430 
-
431  }
-
432  }
-
433 # ifdef _OPENMP
-
434 # pragma omp for schedule (static)
-
435 # endif
-
436  //--------------------------------------- STEP TWO ---------------------
-
437  for (thisTask=0; thisTask<numTasks; thisTask++){
-
438  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
439  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
440  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
441  || (thisPatternQubit1==totMaskQubit1))){
-
442  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
443  partner = thisTask | totMaskQubit2;
-
444  real00 = qureg.stateVec.real[thisTask];
-
445  imag00 = qureg.stateVec.imag[thisTask];
-
446 
-
447  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
448  + delta*qureg.stateVec.real[partner];
-
449  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
450  + delta*qureg.stateVec.imag[partner];
-
451 
-
452  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
453  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
454 
-
455  }
-
456  }
-
457 
-
458 # ifdef _OPENMP
-
459 # pragma omp for schedule (static)
-
460 # endif
-
461  //--------------------------------------- STEP THREE ---------------------
-
462  for (thisTask=0; thisTask<numTasks; thisTask++){
-
463  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
464  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
465  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
466  || (thisPatternQubit1==totMaskQubit1))){
-
467  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
468  partner = thisTask | totMaskQubit2;
-
469  partner = partner ^ totMaskQubit1;
-
470  real00 = qureg.stateVec.real[thisTask];
-
471  imag00 = qureg.stateVec.imag[thisTask];
-
472 
-
473  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
-
474  + delta*qureg.stateVec.real[partner]);
-
475  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
-
476  + delta*qureg.stateVec.imag[partner]);
-
477 
-
478  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
-
479  + delta*real00);
-
480  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
-
481  + delta*imag00);
-
482 
-
483  }
-
484  }
-
485  }
-
486 }
+
402  long long int thisTask;
+
403  long long int partner;
+
404  long long int thisPatternQubit1, thisPatternQubit2;
+
405 
+
406  qreal real00, imag00;
+
407 
+
408 # ifdef _OPENMP
+
409 # pragma omp parallel \
+
410  default (none) \
+
411  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
+
412  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
+
413 # endif
+
414  {
+
415 # ifdef _OPENMP
+
416 # pragma omp for schedule (static)
+
417 # endif
+
418  //--------------------------------------- STEP ONE ---------------------
+
419  for (thisTask=0; thisTask<numTasks; thisTask++){
+
420  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
421  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
422  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
+
423  || (thisPatternQubit2==totMaskQubit2))){
+
424  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
+
425  partner = thisTask | totMaskQubit1;
+
426  real00 = qureg.stateVec.real[thisTask];
+
427  imag00 = qureg.stateVec.imag[thisTask];
+
428 
+
429  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
430  + delta*qureg.stateVec.real[partner];
+
431  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
432  + delta*qureg.stateVec.imag[partner];
+
433 
+
434  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
435  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
436 
+
437  }
+
438  }
+
439 # ifdef _OPENMP
+
440 # pragma omp for schedule (static)
+
441 # endif
+
442  //--------------------------------------- STEP TWO ---------------------
+
443  for (thisTask=0; thisTask<numTasks; thisTask++){
+
444  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
445  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
446  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
+
447  || (thisPatternQubit1==totMaskQubit1))){
+
448  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
+
449  partner = thisTask | totMaskQubit2;
+
450  real00 = qureg.stateVec.real[thisTask];
+
451  imag00 = qureg.stateVec.imag[thisTask];
+
452 
+
453  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
454  + delta*qureg.stateVec.real[partner];
+
455  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
456  + delta*qureg.stateVec.imag[partner];
+
457 
+
458  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
459  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
460 
+
461  }
+
462  }
+
463 
+
464 # ifdef _OPENMP
+
465 # pragma omp for schedule (static)
+
466 # endif
+
467  //--------------------------------------- STEP THREE ---------------------
+
468  for (thisTask=0; thisTask<numTasks; thisTask++){
+
469  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
470  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
471  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
+
472  || (thisPatternQubit1==totMaskQubit1))){
+
473  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
+
474  partner = thisTask | totMaskQubit2;
+
475  partner = partner ^ totMaskQubit1;
+
476  real00 = qureg.stateVec.real[thisTask];
+
477  imag00 = qureg.stateVec.imag[thisTask];
+
478 
+
479  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
+
480  + delta*qureg.stateVec.real[partner]);
+
481  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
+
482  + delta*qureg.stateVec.imag[partner]);
+
483 
+
484  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
+
485  + delta*real00);
+
486  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
+
487  + delta*imag00);
+
488 
+
489  }
+
490  }
+
491  }
+
492 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -2606,63 +2611,63 @@

-

Definition at line 488 of file QuEST_cpu.c.

-
488  {
-
489  long long int numTasks = qureg.numAmpsPerChunk;
-
490  long long int innerMaskQubit1 = 1LL << qubit1;
-
491  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
492  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
493  long long int innerMaskQubit2 = 1LL << qubit2;
-
494  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
495  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
496  // correct for being in a particular chunk
-
497  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
-
498 
-
499 
-
500  long long int thisTask;
-
501  long long int partner;
-
502  long long int thisPatternQubit1, thisPatternQubit2;
-
503 
-
504  qreal real00, imag00;
+

Definition at line 494 of file QuEST_cpu.c.

+
494  {
+
495  long long int numTasks = qureg.numAmpsPerChunk;
+
496  long long int innerMaskQubit1 = 1LL << qubit1;
+
497  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
+
498  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
+
499  long long int innerMaskQubit2 = 1LL << qubit2;
+
500  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
+
501  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
+
502  // correct for being in a particular chunk
+
503  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
+
504 
505 
-
506 # ifdef _OPENMP
-
507 # pragma omp parallel \
-
508  default (none) \
-
509  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
-
510  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
511 # endif
-
512  {
-
513 
-
514 # ifdef _OPENMP
-
515 # pragma omp for schedule (static)
-
516 # endif
-
517  //--------------------------------------- STEP ONE ---------------------
-
518  for (thisTask=0; thisTask<numTasks; thisTask ++){
-
519  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
520  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
521  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
522  || (thisPatternQubit2==totMaskQubit2))){
-
523  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
524  partner = thisTask | totMaskQubit1;
-
525  real00 = qureg.stateVec.real[thisTask];
-
526  imag00 = qureg.stateVec.imag[thisTask];
-
527 
-
528  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
529  + delta*qureg.stateVec.real[partner];
-
530  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
531  + delta*qureg.stateVec.imag[partner];
-
532 
-
533  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
534  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
535 
-
536  }
-
537  }
-
538  }
-
539 }
+
506  long long int thisTask;
+
507  long long int partner;
+
508  long long int thisPatternQubit1, thisPatternQubit2;
+
509 
+
510  qreal real00, imag00;
+
511 
+
512 # ifdef _OPENMP
+
513 # pragma omp parallel \
+
514  default (none) \
+
515  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
+
516  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
+
517 # endif
+
518  {
+
519 
+
520 # ifdef _OPENMP
+
521 # pragma omp for schedule (static)
+
522 # endif
+
523  //--------------------------------------- STEP ONE ---------------------
+
524  for (thisTask=0; thisTask<numTasks; thisTask ++){
+
525  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
526  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
527  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
+
528  || (thisPatternQubit2==totMaskQubit2))){
+
529  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
+
530  partner = thisTask | totMaskQubit1;
+
531  real00 = qureg.stateVec.real[thisTask];
+
532  imag00 = qureg.stateVec.imag[thisTask];
+
533 
+
534  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
535  + delta*qureg.stateVec.real[partner];
+
536  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
537  + delta*qureg.stateVec.imag[partner];
+
538 
+
539  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
540  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
541 
+
542  }
+
543  }
+
544  }
+
545 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -2710,109 +2715,109 @@

-

Definition at line 632 of file QuEST_cpu.c.

-
633  {
-
634 
-
635  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
636  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
637  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
638  long long int thisInnerBlockQ2,
-
639  thisOuterColumn, // current column in density matrix
-
640  thisIndex, // current index in (density matrix representation) state vector
-
641  thisIndexInPairVector,
-
642  thisIndexInOuterColumn,
-
643  thisIndexInInnerBlockQ1,
-
644  thisIndexInInnerBlockQ2,
-
645  thisInnerBlockQ1InInnerBlockQ2;
-
646  int outerBitQ1, outerBitQ2;
-
647 
-
648  long long int thisTask;
-
649  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
650 
-
651  // set dimensions
-
652  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
653  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
654  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
655  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
656  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
657  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
658  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
659 
-
660 //# if 0
-
661 # ifdef _OPENMP
-
662 # pragma omp parallel \
-
663  default (none) \
-
664  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
665  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
-
666  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
667  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
-
668  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
669 # endif
-
670  {
-
671 # ifdef _OPENMP
-
672 # pragma omp for schedule (static)
-
673 # endif
-
674 //# endif
-
675  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
676  // treat this as iterating over all columns, then iterating over half the values
-
677  // within one column.
-
678  // If this function has been called, this process' chunk contains half an
-
679  // outer block or less
-
680  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
681  // we want to process all columns in the density matrix,
-
682  // updating the values for half of each column (one half of each inner block)
-
683  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
684  // thisTask % sizeOuterQuarterColumn
-
685  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
686  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
687  // thisTask % sizeInnerQuarterBlockQ2;
-
688  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
689  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
690  // thisTask % sizeInnerHalfBlockQ1;
-
691  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
692 
-
693  // get index in state vector corresponding to upper inner block
-
694  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
695  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
696 
-
697  // check if we are in the upper or lower half of an outer block for Q1
-
698  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
699  // if we are in the lower half of an outer block, shift to be in the lower half
-
700  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
701  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
702 
-
703  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
-
704  // Find correct index in pairStateVector
-
705  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
-
706  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
-
707 
-
708  // check if we are in the upper or lower half of an outer block for Q2
-
709  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
710  // if we are in the lower half of an outer block, shift to be in the lower half
-
711  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
712  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+

Definition at line 638 of file QuEST_cpu.c.

+
639  {
+
640 
+
641  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
642  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
643  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
644  long long int thisInnerBlockQ2,
+
645  thisOuterColumn, // current column in density matrix
+
646  thisIndex, // current index in (density matrix representation) state vector
+
647  thisIndexInPairVector,
+
648  thisIndexInOuterColumn,
+
649  thisIndexInInnerBlockQ1,
+
650  thisIndexInInnerBlockQ2,
+
651  thisInnerBlockQ1InInnerBlockQ2;
+
652  int outerBitQ1, outerBitQ2;
+
653 
+
654  long long int thisTask;
+
655  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
656 
+
657  // set dimensions
+
658  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
659  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
660  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
661  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
662  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
663  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
664  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
665 
+
666 //# if 0
+
667 # ifdef _OPENMP
+
668 # pragma omp parallel \
+
669  default (none) \
+
670  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
+
671  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
+
672  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
+
673  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
+
674  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
+
675 # endif
+
676  {
+
677 # ifdef _OPENMP
+
678 # pragma omp for schedule (static)
+
679 # endif
+
680 //# endif
+
681  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
682  // treat this as iterating over all columns, then iterating over half the values
+
683  // within one column.
+
684  // If this function has been called, this process' chunk contains half an
+
685  // outer block or less
+
686  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
687  // we want to process all columns in the density matrix,
+
688  // updating the values for half of each column (one half of each inner block)
+
689  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
690  // thisTask % sizeOuterQuarterColumn
+
691  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
692  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
693  // thisTask % sizeInnerQuarterBlockQ2;
+
694  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
695  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
696  // thisTask % sizeInnerHalfBlockQ1;
+
697  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
+
698 
+
699  // get index in state vector corresponding to upper inner block
+
700  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
701  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
702 
+
703  // check if we are in the upper or lower half of an outer block for Q1
+
704  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
705  // if we are in the lower half of an outer block, shift to be in the lower half
+
706  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
707  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+
708 
+
709  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
+
710  // Find correct index in pairStateVector
+
711  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
+
712  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
713 
-
714 
-
715  // NOTE: at this point thisIndex should be the index of the element we want to
-
716  // dephase in the chunk of the state vector on this process, in the
-
717  // density matrix representation.
-
718 
-
719 
-
720  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
721  // + pair[thisIndexInPairVector])/2
-
722  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
723  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
-
724 
-
725  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
726  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
-
727  }
-
728  }
-
729 
-
730 }
+
714  // check if we are in the upper or lower half of an outer block for Q2
+
715  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
716  // if we are in the lower half of an outer block, shift to be in the lower half
+
717  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
718  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
719 
+
720 
+
721  // NOTE: at this point thisIndex should be the index of the element we want to
+
722  // dephase in the chunk of the state vector on this process, in the
+
723  // density matrix representation.
+
724 
+
725 
+
726  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
727  // + pair[thisIndexInPairVector])/2
+
728  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
+
729  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
+
730 
+
731  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
+
732  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
+
733  }
+
734  }
+
735 
+
736 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -2848,41 +2853,41 @@

-

Definition at line 48 of file QuEST_cpu.c.

-
48  {
-
49  long long int numTasks = qureg.numAmpsPerChunk;
-
50  long long int innerMask = 1LL << targetQubit;
-
51  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
52 
-
53  long long int thisTask;
-
54  long long int thisPattern;
-
55  long long int totMask = innerMask|outerMask;
-
56 
-
57 # ifdef _OPENMP
-
58 # pragma omp parallel \
-
59  default (none) \
-
60  shared (innerMask,outerMask,totMask,qureg,retain,numTasks, targetQubit) \
-
61  private (thisTask,thisPattern)
-
62 # endif
-
63  {
-
64 # ifdef _OPENMP
-
65 # pragma omp for schedule (static)
-
66 # endif
-
67  for (thisTask=0; thisTask<numTasks; thisTask++){
-
68  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
69  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
70  // do dephase
-
71  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
72  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
73  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
74  }
-
75  }
-
76  }
-
77 }
+

Definition at line 54 of file QuEST_cpu.c.

+
54  {
+
55  long long int numTasks = qureg.numAmpsPerChunk;
+
56  long long int innerMask = 1LL << targetQubit;
+
57  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
58 
+
59  long long int thisTask;
+
60  long long int thisPattern;
+
61  long long int totMask = innerMask|outerMask;
+
62 
+
63 # ifdef _OPENMP
+
64 # pragma omp parallel \
+
65  default (none) \
+
66  shared (innerMask,outerMask,totMask,qureg,retain,numTasks, targetQubit) \
+
67  private (thisTask,thisPattern)
+
68 # endif
+
69  {
+
70 # ifdef _OPENMP
+
71 # pragma omp for schedule (static)
+
72 # endif
+
73  for (thisTask=0; thisTask<numTasks; thisTask++){
+
74  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
75  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
76  // do dephase
+
77  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
78  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
79  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
80  }
+
81  }
+
82  }
+
83 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and Qureg::stateVec.

-

Referenced by densmatr_mixDampingDistributed(), and densmatr_mixDephasing().

+

Referenced by densmatr_mixDampingDistributed(), and densmatr_mixDephasing().

@@ -2902,17 +2907,17 @@

-

Definition at line 3268 of file QuEST_cpu.c.

-
3268  {
-
3269  int parity = 0;
-
3270  while (mask) {
-
3271  parity = !parity;
-
3272  mask = mask & (mask-1);
-
3273  }
-
3274  return parity;
-
3275 }
+

Definition at line 3307 of file QuEST_cpu.c.

+
3307  {
+
3308  int parity = 0;
+
3309  while (mask) {
+
3310  parity = !parity;
+
3311  mask = mask & (mask-1);
+
3312  }
+
3313  return parity;
+
3314 }
-

Referenced by statevec_multiControlledMultiRotateZ(), and statevec_multiRotateZ().

+

Referenced by statevec_multiControlledMultiRotateZ(), and statevec_multiRotateZ().

@@ -2954,21 +2959,21 @@

-

Definition at line 744 of file QuEST_cpu.c.

-
744  {
-
745  long long int i;
-
746 # ifdef _OPENMP
-
747 # pragma omp parallel for schedule (static)
-
748 # endif
-
749  for (i=startInd; i < startInd+numAmps; i++) {
-
750  qureg.stateVec.real[i] /= norm;
-
751  qureg.stateVec.imag[i] /= norm;
-
752  }
-
753 }
+

Definition at line 750 of file QuEST_cpu.c.

+
750  {
+
751  long long int i;
+
752 # ifdef _OPENMP
+
753 # pragma omp parallel for schedule (static)
+
754 # endif
+
755  for (i=startInd; i < startInd+numAmps; i++) {
+
756  qureg.stateVec.real[i] /= norm;
+
757  qureg.stateVec.imag[i] /= norm;
+
758  }
+
759 }

References Qureg::stateVec.

-

Referenced by alternateNormZeroingSomeAmpBlocks(), and densmatr_collapseToKnownProbOutcome().

+

Referenced by alternateNormZeroingSomeAmpBlocks(), and densmatr_collapseToKnownProbOutcome().

@@ -2998,12 +3003,12 @@

-

Definition at line 1897 of file QuEST_cpu.c.

-
1897  {
-
1898  return *(int*)a - *(int*)b;
-
1899 }
+

Definition at line 1908 of file QuEST_cpu.c.

+
1908  {
+
1909  return *(int*)a - *(int*)b;
+
1910 }
-

Referenced by statevec_multiControlledMultiQubitUnitaryLocal().

+

Referenced by statevec_multiControlledMultiQubitUnitaryLocal().

@@ -3033,41 +3038,41 @@

-

Definition at line 4007 of file QuEST_cpu.c.

-
4007  {
-
4008 
-
4009  // each node/chunk modifies only its values in an embarrassingly parallelisable way
-
4010  long long int numAmps = qureg.numAmpsPerChunk;
-
4011 
-
4012  qreal* stateRe = qureg.stateVec.real;
-
4013  qreal* stateIm = qureg.stateVec.imag;
-
4014  qreal* opRe = op.real;
-
4015  qreal* opIm = op.imag;
-
4016 
-
4017  qreal a,b,c,d;
-
4018  long long int index;
-
4019 
-
4020 # ifdef _OPENMP
-
4021 # pragma omp parallel \
-
4022  shared (stateRe,stateIm, opRe,opIm, numAmps) \
-
4023  private (index, a,b,c,d)
-
4024 # endif
-
4025  {
-
4026 # ifdef _OPENMP
-
4027 # pragma omp for schedule (static)
-
4028 # endif
-
4029  for (index=0LL; index<numAmps; index++) {
-
4030  a = stateRe[index];
-
4031  b = stateIm[index];
-
4032  c = opRe[index];
-
4033  d = opIm[index];
-
4034 
-
4035  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
4036  stateRe[index] = a*c - b*d;
-
4037  stateIm[index] = a*d + b*c;
-
4038  }
-
4039  }
-
4040 }
+

Definition at line 4047 of file QuEST_cpu.c.

+
4047  {
+
4048 
+
4049  // each node/chunk modifies only its values in an embarrassingly parallelisable way
+
4050  long long int numAmps = qureg.numAmpsPerChunk;
+
4051 
+
4052  qreal* stateRe = qureg.stateVec.real;
+
4053  qreal* stateIm = qureg.stateVec.imag;
+
4054  qreal* opRe = op.real;
+
4055  qreal* opIm = op.imag;
+
4056 
+
4057  qreal a,b,c,d;
+
4058  long long int index;
+
4059 
+
4060 # ifdef _OPENMP
+
4061 # pragma omp parallel \
+
4062  shared (stateRe,stateIm, opRe,opIm, numAmps) \
+
4063  private (index, a,b,c,d)
+
4064 # endif
+
4065  {
+
4066 # ifdef _OPENMP
+
4067 # pragma omp for schedule (static)
+
4068 # endif
+
4069  for (index=0LL; index<numAmps; index++) {
+
4070  a = stateRe[index];
+
4071  b = stateIm[index];
+
4072  c = opRe[index];
+
4073  d = opIm[index];
+
4074 
+
4075  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
4076  stateRe[index] = a*c - b*d;
+
4077  stateIm[index] = a*d + b*c;
+
4078  }
+
4079  }
+
4080 }

References DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, DiagonalOp::real, and Qureg::stateVec.

@@ -3159,102 +3164,102 @@

-

Definition at line 4305 of file QuEST_cpu.c.

-
4310 {
-
4311  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4312 
-
4313  // note partitions of qubits, coeffs, exponents and overrideInds are stored flat
-
4314 
-
4315  // thread-shared vaes
-
4316  int chunkId = qureg.chunkId;
-
4317  long long int numAmps = qureg.numAmpsPerChunk;
-
4318  qreal* stateRe = qureg.stateVec.real;
-
4319  qreal* stateIm = qureg.stateVec.imag;
-
4320 
-
4321  // thread-private vars
-
4322  long long int index, globalAmpInd;
-
4323  int r, q, i, t, found, flatInd;
-
4324  qreal phase, c, s, re, im;
-
4325 
-
4326  // each thread has a private static array of length >= numRegs (private var-length is illegal)
-
4327  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
-
4328 
-
4329 # ifdef _OPENMP
-
4330 # pragma omp parallel \
-
4331  default (none) \
-
4332  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, coeffs,exponents,numTermsPerReg, overrideInds,overridePhases,numOverrides, conj) \
-
4333  private (index,globalAmpInd, r,q,i,t,flatInd, found, phaseInds,phase, c,s,re,im)
-
4334 # endif
-
4335  {
-
4336 # ifdef _OPENMP
-
4337 # pragma omp for schedule (static)
-
4338 # endif
-
4339  for (index=0LL; index<numAmps; index++) {
-
4340 
-
4341  // determine global amplitude index
-
4342  globalAmpInd = chunkId * numAmps + index;
-
4343 
-
4344  // determine phase indices
-
4345  flatInd = 0;
-
4346  for (r=0; r<numRegs; r++) {
-
4347  phaseInds[r] = 0LL;
-
4348 
-
4349  if (encoding == UNSIGNED) {
-
4350  for (q=0; q<numQubitsPerReg[r]; q++)
-
4351  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
-
4352  }
-
4353  else if (encoding == TWOS_COMPLEMENT) {
-
4354  for (q=0; q<numQubitsPerReg[r]-1; q++)
-
4355  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
4356  // use final qubit to indicate sign
-
4357  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
4358  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
-
4359  }
-
4360  }
-
4361 
-
4362  // determine if this phase index has an overriden value (i < numOverrides)
-
4363  for (i=0; i<numOverrides; i++) {
-
4364  found = 1;
-
4365  for (r=0; r<numRegs; r++) {
-
4366  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
-
4367  found = 0;
-
4368  break;
-
4369  }
-
4370  }
-
4371  if (found)
-
4372  break;
-
4373  }
-
4374 
-
4375  // compute the phase (unless overriden)
-
4376  phase = 0;
-
4377  if (i < numOverrides)
-
4378  phase = overridePhases[i];
-
4379  else {
-
4380  flatInd = 0;
-
4381  for (r=0; r<numRegs; r++) {
-
4382  for (t=0; t<numTermsPerReg[r]; t++) {
-
4383  phase += coeffs[flatInd] * pow(phaseInds[r], exponents[flatInd]);
-
4384  flatInd++;
-
4385  }
-
4386  }
-
4387  }
-
4388 
-
4389  // negate phase to conjugate operator
-
4390  if (conj)
-
4391  phase *= -1;
-
4392 
-
4393  // modify amp to amp * exp(i phase)
-
4394  c = cos(phase);
-
4395  s = sin(phase);
-
4396  re = stateRe[index];
-
4397  im = stateIm[index];
-
4398 
-
4399  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4400  stateRe[index] = re*c - im*s;
-
4401  stateIm[index] = re*s + im*c;
-
4402  }
-
4403  }
-
4404 }
+

Definition at line 4345 of file QuEST_cpu.c.

+
4350 {
+
4351  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4352 
+
4353  // note partitions of qubits, coeffs, exponents and overrideInds are stored flat
+
4354 
+
4355  // thread-shared vaes
+
4356  int chunkId = qureg.chunkId;
+
4357  long long int numAmps = qureg.numAmpsPerChunk;
+
4358  qreal* stateRe = qureg.stateVec.real;
+
4359  qreal* stateIm = qureg.stateVec.imag;
+
4360 
+
4361  // thread-private vars
+
4362  long long int index, globalAmpInd;
+
4363  int r, q, i, t, found, flatInd;
+
4364  qreal phase, c, s, re, im;
+
4365 
+
4366  // each thread has a private static array of length >= numRegs (private var-length is illegal)
+
4367  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
+
4368 
+
4369 # ifdef _OPENMP
+
4370 # pragma omp parallel \
+
4371  default (none) \
+
4372  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, coeffs,exponents,numTermsPerReg, overrideInds,overridePhases,numOverrides, conj) \
+
4373  private (index,globalAmpInd, r,q,i,t,flatInd, found, phaseInds,phase, c,s,re,im)
+
4374 # endif
+
4375  {
+
4376 # ifdef _OPENMP
+
4377 # pragma omp for schedule (static)
+
4378 # endif
+
4379  for (index=0LL; index<numAmps; index++) {
+
4380 
+
4381  // determine global amplitude index
+
4382  globalAmpInd = chunkId * numAmps + index;
+
4383 
+
4384  // determine phase indices
+
4385  flatInd = 0;
+
4386  for (r=0; r<numRegs; r++) {
+
4387  phaseInds[r] = 0LL;
+
4388 
+
4389  if (encoding == UNSIGNED) {
+
4390  for (q=0; q<numQubitsPerReg[r]; q++)
+
4391  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
+
4392  }
+
4393  else if (encoding == TWOS_COMPLEMENT) {
+
4394  for (q=0; q<numQubitsPerReg[r]-1; q++)
+
4395  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
4396  // use final qubit to indicate sign
+
4397  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
4398  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
+
4399  }
+
4400  }
+
4401 
+
4402  // determine if this phase index has an overriden value (i < numOverrides)
+
4403  for (i=0; i<numOverrides; i++) {
+
4404  found = 1;
+
4405  for (r=0; r<numRegs; r++) {
+
4406  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
+
4407  found = 0;
+
4408  break;
+
4409  }
+
4410  }
+
4411  if (found)
+
4412  break;
+
4413  }
+
4414 
+
4415  // compute the phase (unless overriden)
+
4416  phase = 0;
+
4417  if (i < numOverrides)
+
4418  phase = overridePhases[i];
+
4419  else {
+
4420  flatInd = 0;
+
4421  for (r=0; r<numRegs; r++) {
+
4422  for (t=0; t<numTermsPerReg[r]; t++) {
+
4423  phase += coeffs[flatInd] * pow(phaseInds[r], exponents[flatInd]);
+
4424  flatInd++;
+
4425  }
+
4426  }
+
4427  }
+
4428 
+
4429  // negate phase to conjugate operator
+
4430  if (conj)
+
4431  phase *= -1;
+
4432 
+
4433  // modify amp to amp * exp(i phase)
+
4434  c = cos(phase);
+
4435  s = sin(phase);
+
4436  re = stateRe[index];
+
4437  im = stateIm[index];
+
4438 
+
4439  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4440  stateRe[index] = re*c - im*s;
+
4441  stateIm[index] = re*s + im*c;
+
4442  }
+
4443  }
+
4444 }

References Qureg::chunkId, extractBit(), MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, TWOS_COMPLEMENT, and UNSIGNED.

@@ -3346,160 +3351,160 @@

-

Definition at line 4406 of file QuEST_cpu.c.

-
4412  {
-
4413  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4414 
-
4415  // note partitions of qubits, overrideInds are stored flat
-
4416 
-
4417  // thread-shared vaes
-
4418  int chunkId = qureg.chunkId;
-
4419  long long int numAmps = qureg.numAmpsPerChunk;
-
4420  qreal* stateRe = qureg.stateVec.real;
-
4421  qreal* stateIm = qureg.stateVec.imag;
-
4422 
-
4423  // thread-private vars
-
4424  long long int index, globalAmpInd;
-
4425  int r, q, i, found, flatInd;
-
4426  qreal phase, norm, prod, dist, c, s, re, im;
-
4427 
-
4428  // each thread has a private static array of length >= numRegs (private var-length is illegal)
-
4429  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
-
4430 
-
4431 # ifdef _OPENMP
-
4432 # pragma omp parallel \
-
4433  default (none) \
-
4434  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, phaseFuncName,params,numParams, overrideInds,overridePhases,numOverrides, conj) \
-
4435  private (index,globalAmpInd, r,q,i,flatInd, found, phaseInds,phase,norm,prod,dist, c,s,re,im)
-
4436 # endif
-
4437  {
-
4438 # ifdef _OPENMP
-
4439 # pragma omp for schedule (static)
-
4440 # endif
-
4441  for (index=0LL; index<numAmps; index++) {
-
4442 
-
4443  // determine global amplitude index
-
4444  globalAmpInd = chunkId * numAmps + index;
-
4445 
-
4446  // determine phase indices
-
4447  flatInd = 0;
-
4448  for (r=0; r<numRegs; r++) {
-
4449  phaseInds[r] = 0LL;
-
4450 
-
4451  if (encoding == UNSIGNED) {
-
4452  for (q=0; q<numQubitsPerReg[r]; q++)
-
4453  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
-
4454  }
-
4455  else if (encoding == TWOS_COMPLEMENT) {
-
4456  for (q=0; q<numQubitsPerReg[r]-1; q++)
-
4457  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
4458  // use final qubit to indicate sign
-
4459  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
4460  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
-
4461  }
-
4462  }
-
4463 
-
4464  // determine if this phase index has an overriden value (i < numOverrides)
-
4465  for (i=0; i<numOverrides; i++) {
-
4466  found = 1;
-
4467  for (r=0; r<numRegs; r++) {
-
4468  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
-
4469  found = 0;
-
4470  break;
-
4471  }
-
4472  }
-
4473  if (found)
-
4474  break;
-
4475  }
-
4476 
-
4477  // compute the phase (unless overriden)
-
4478  phase = 0;
-
4479  if (i < numOverrides)
-
4480  phase = overridePhases[i];
-
4481  else {
-
4482  // compute norm related phases
-
4483  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
-
4484  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
-
4485  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
4486 
-
4487  norm = 0;
-
4488  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
4489  for (r=0; r<numRegs; r++)
-
4490  norm += (phaseInds[r] - params[2+r])*(phaseInds[r] - params[2+r]);
-
4491  }
-
4492  else
-
4493  for (r=0; r<numRegs; r++)
-
4494  norm += phaseInds[r]*phaseInds[r];
-
4495  norm = sqrt(norm);
-
4496 
-
4497  if (phaseFuncName == NORM)
-
4498  phase = norm;
-
4499  else if (phaseFuncName == INVERSE_NORM)
-
4500  phase = (norm == 0.)? params[0] : 1/norm;
-
4501  else if (phaseFuncName == SCALED_NORM)
-
4502  phase = params[0] * norm;
-
4503  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
-
4504  phase = (norm == 0.)? params[1] : params[0] / norm;
-
4505  }
-
4506  // compute product related phases
-
4507  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
-
4508  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
-
4509 
-
4510  prod = 1;
-
4511  for (r=0; r<numRegs; r++)
-
4512  prod *= phaseInds[r];
-
4513 
-
4514  if (phaseFuncName == PRODUCT)
-
4515  phase = prod;
-
4516  else if (phaseFuncName == INVERSE_PRODUCT)
-
4517  phase = (prod == 0.)? params[0] : 1/prod;
-
4518  else if (phaseFuncName == SCALED_PRODUCT)
-
4519  phase = params[0] * prod;
-
4520  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
-
4521  phase = (prod == 0.)? params[1] : params[0] / prod;
-
4522  }
-
4523  // compute Euclidean distance related phases
-
4524  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
-
4525  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
-
4526  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
4527 
-
4528  dist = 0;
-
4529  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
4530  for (r=0; r<numRegs; r+=2)
-
4531  dist += (phaseInds[r+1] - phaseInds[r] - params[2+r/2])*(phaseInds[r+1] - phaseInds[r] - params[2+r/2]);
-
4532  }
-
4533  else
-
4534  for (r=0; r<numRegs; r+=2)
-
4535  dist += (phaseInds[r+1] - phaseInds[r])*(phaseInds[r+1] - phaseInds[r]);
-
4536  dist = sqrt(dist);
-
4537 
-
4538  if (phaseFuncName == DISTANCE)
-
4539  phase = dist;
-
4540  else if (phaseFuncName == INVERSE_DISTANCE)
-
4541  phase = (dist == 0.)? params[0] : 1/dist;
-
4542  else if (phaseFuncName == SCALED_DISTANCE)
-
4543  phase = params[0] * dist;
-
4544  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
-
4545  phase = (dist == 0.)? params[1] : params[0] / dist;
-
4546  }
-
4547  }
-
4548 
-
4549  // negate phase to conjugate operator
-
4550  if (conj)
-
4551  phase *= -1;
-
4552 
-
4553  // modify amp to amp * exp(i phase)
-
4554  c = cos(phase);
-
4555  s = sin(phase);
-
4556  re = stateRe[index];
-
4557  im = stateIm[index];
-
4558 
-
4559  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4560  stateRe[index] = re*c - im*s;
-
4561  stateIm[index] = re*s + im*c;
-
4562  }
-
4563  }
-
4564 }
+

Definition at line 4446 of file QuEST_cpu.c.

+
4452  {
+
4453  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4454 
+
4455  // note partitions of qubits, overrideInds are stored flat
+
4456 
+
4457  // thread-shared vaes
+
4458  int chunkId = qureg.chunkId;
+
4459  long long int numAmps = qureg.numAmpsPerChunk;
+
4460  qreal* stateRe = qureg.stateVec.real;
+
4461  qreal* stateIm = qureg.stateVec.imag;
+
4462 
+
4463  // thread-private vars
+
4464  long long int index, globalAmpInd;
+
4465  int r, q, i, found, flatInd;
+
4466  qreal phase, norm, prod, dist, c, s, re, im;
+
4467 
+
4468  // each thread has a private static array of length >= numRegs (private var-length is illegal)
+
4469  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
+
4470 
+
4471 # ifdef _OPENMP
+
4472 # pragma omp parallel \
+
4473  default (none) \
+
4474  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, phaseFuncName,params,numParams, overrideInds,overridePhases,numOverrides, conj) \
+
4475  private (index,globalAmpInd, r,q,i,flatInd, found, phaseInds,phase,norm,prod,dist, c,s,re,im)
+
4476 # endif
+
4477  {
+
4478 # ifdef _OPENMP
+
4479 # pragma omp for schedule (static)
+
4480 # endif
+
4481  for (index=0LL; index<numAmps; index++) {
+
4482 
+
4483  // determine global amplitude index
+
4484  globalAmpInd = chunkId * numAmps + index;
+
4485 
+
4486  // determine phase indices
+
4487  flatInd = 0;
+
4488  for (r=0; r<numRegs; r++) {
+
4489  phaseInds[r] = 0LL;
+
4490 
+
4491  if (encoding == UNSIGNED) {
+
4492  for (q=0; q<numQubitsPerReg[r]; q++)
+
4493  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
+
4494  }
+
4495  else if (encoding == TWOS_COMPLEMENT) {
+
4496  for (q=0; q<numQubitsPerReg[r]-1; q++)
+
4497  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
4498  // use final qubit to indicate sign
+
4499  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
4500  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
+
4501  }
+
4502  }
+
4503 
+
4504  // determine if this phase index has an overriden value (i < numOverrides)
+
4505  for (i=0; i<numOverrides; i++) {
+
4506  found = 1;
+
4507  for (r=0; r<numRegs; r++) {
+
4508  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
+
4509  found = 0;
+
4510  break;
+
4511  }
+
4512  }
+
4513  if (found)
+
4514  break;
+
4515  }
+
4516 
+
4517  // compute the phase (unless overriden)
+
4518  phase = 0;
+
4519  if (i < numOverrides)
+
4520  phase = overridePhases[i];
+
4521  else {
+
4522  // compute norm related phases
+
4523  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
+
4524  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
+
4525  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
4526 
+
4527  norm = 0;
+
4528  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
4529  for (r=0; r<numRegs; r++)
+
4530  norm += (phaseInds[r] - params[2+r])*(phaseInds[r] - params[2+r]);
+
4531  }
+
4532  else
+
4533  for (r=0; r<numRegs; r++)
+
4534  norm += phaseInds[r]*phaseInds[r];
+
4535  norm = sqrt(norm);
+
4536 
+
4537  if (phaseFuncName == NORM)
+
4538  phase = norm;
+
4539  else if (phaseFuncName == INVERSE_NORM)
+
4540  phase = (norm == 0.)? params[0] : 1/norm; // smallest non-zero norm is 1
+
4541  else if (phaseFuncName == SCALED_NORM)
+
4542  phase = params[0] * norm;
+
4543  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
+
4544  phase = (norm <= REAL_EPS)? params[1] : params[0] / norm; // unless shifted closer to zero
+
4545  }
+
4546  // compute product related phases
+
4547  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
+
4548  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
+
4549 
+
4550  prod = 1;
+
4551  for (r=0; r<numRegs; r++)
+
4552  prod *= phaseInds[r];
+
4553 
+
4554  if (phaseFuncName == PRODUCT)
+
4555  phase = prod;
+
4556  else if (phaseFuncName == INVERSE_PRODUCT)
+
4557  phase = (prod == 0.)? params[0] : 1/prod; // smallest non-zero product norm is +- 1
+
4558  else if (phaseFuncName == SCALED_PRODUCT)
+
4559  phase = params[0] * prod;
+
4560  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
+
4561  phase = (prod == 0.)? params[1] : params[0] / prod;
+
4562  }
+
4563  // compute Euclidean distance related phases
+
4564  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
+
4565  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
+
4566  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
4567 
+
4568  dist = 0;
+
4569  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
4570  for (r=0; r<numRegs; r+=2)
+
4571  dist += (phaseInds[r] - phaseInds[r+1] - params[2+r/2])*(phaseInds[r] - phaseInds[r+1] - params[2+r/2]);
+
4572  }
+
4573  else
+
4574  for (r=0; r<numRegs; r+=2)
+
4575  dist += (phaseInds[r+1] - phaseInds[r])*(phaseInds[r+1] - phaseInds[r]);
+
4576  dist = sqrt(dist);
+
4577 
+
4578  if (phaseFuncName == DISTANCE)
+
4579  phase = dist;
+
4580  else if (phaseFuncName == INVERSE_DISTANCE)
+
4581  phase = (dist == 0.)? params[0] : 1/dist; // smallest non-zero dist is 1
+
4582  else if (phaseFuncName == SCALED_DISTANCE)
+
4583  phase = params[0] * dist;
+
4584  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
+
4585  phase = (dist <= REAL_EPS)? params[1] : params[0] / dist; // unless shifted closer to 0
+
4586  }
+
4587  }
+
4588 
+
4589  // negate phase to conjugate operator
+
4590  if (conj)
+
4591  phase *= -1;
+
4592 
+
4593  // modify amp to amp * exp(i phase)
+
4594  c = cos(phase);
+
4595  s = sin(phase);
+
4596  re = stateRe[index];
+
4597  im = stateIm[index];
+
4598 
+
4599  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4600  stateRe[index] = re*c - im*s;
+
4601  stateIm[index] = re*s + im*c;
+
4602  }
+
4603  }
+
4604 }

References Qureg::chunkId, DISTANCE, extractBit(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, Qureg::numAmpsPerChunk, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, Qureg::stateVec, TWOS_COMPLEMENT, and UNSIGNED.

@@ -3585,78 +3590,78 @@

-

Definition at line 4228 of file QuEST_cpu.c.

-
4233 {
-
4234  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4235 
-
4236  // thread shared vars
-
4237  int chunkId = qureg.chunkId;
-
4238  long long int numAmps = qureg.numAmpsPerChunk;
-
4239  qreal* stateRe = qureg.stateVec.real;
-
4240  qreal* stateIm = qureg.stateVec.imag;
-
4241 
-
4242  // thread private vars
-
4243  long long int index, globalAmpInd, phaseInd;
-
4244  int i, t, q;
-
4245  qreal phase, c, s, re, im;
-
4246 
-
4247 # ifdef _OPENMP
-
4248 # pragma omp parallel \
-
4249  default (none) \
-
4250  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubits,encoding, coeffs,exponents,numTerms, overrideInds,overridePhases,numOverrides, conj) \
-
4251  private (index, globalAmpInd, phaseInd, i,t,q, phase, c,s,re,im)
-
4252 # endif
-
4253  {
-
4254 # ifdef _OPENMP
-
4255 # pragma omp for schedule (static)
-
4256 # endif
-
4257  for (index=0LL; index<numAmps; index++) {
-
4258 
-
4259  // determine global amplitude index
-
4260  globalAmpInd = chunkId * numAmps + index;
-
4261 
-
4262  // determine phase index of {qubits}
-
4263  phaseInd = 0LL;
-
4264  if (encoding == UNSIGNED) {
-
4265  for (q=0; q<numQubits; q++) // use significance order specified by {qubits}
-
4266  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
4267  }
-
4268  else if (encoding == TWOS_COMPLEMENT) {
-
4269  for (q=0; q<numQubits-1; q++) // use final qubit to indicate sign
-
4270  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
4271  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
-
4272  phaseInd -= (1LL << (numQubits-1));
-
4273  }
-
4274 
-
4275  // determine if this phase index has an overriden value (i < numOverrides)
-
4276  for (i=0; i<numOverrides; i++)
-
4277  if (phaseInd == overrideInds[i])
-
4278  break;
-
4279 
-
4280  // determine phase from {coeffs}, {exponents} (unless overriden)
-
4281  phase = 0;
-
4282  if (i < numOverrides)
-
4283  phase = overridePhases[i];
-
4284  else
-
4285  for (t=0; t<numTerms; t++)
-
4286  phase += coeffs[t] * pow(phaseInd, exponents[t]);
-
4287 
-
4288  // negate phase to conjugate operator
-
4289  if (conj)
-
4290  phase *= -1;
-
4291 
-
4292  // modify amp to amp * exp(i phase)
-
4293  c = cos(phase);
-
4294  s = sin(phase);
-
4295  re = stateRe[index];
-
4296  im = stateIm[index];
-
4297 
-
4298  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4299  stateRe[index] = re*c - im*s;
-
4300  stateIm[index] = re*s + im*c;
-
4301  }
-
4302  }
-
4303 }
+

Definition at line 4268 of file QuEST_cpu.c.

+
4273 {
+
4274  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4275 
+
4276  // thread shared vars
+
4277  int chunkId = qureg.chunkId;
+
4278  long long int numAmps = qureg.numAmpsPerChunk;
+
4279  qreal* stateRe = qureg.stateVec.real;
+
4280  qreal* stateIm = qureg.stateVec.imag;
+
4281 
+
4282  // thread private vars
+
4283  long long int index, globalAmpInd, phaseInd;
+
4284  int i, t, q;
+
4285  qreal phase, c, s, re, im;
+
4286 
+
4287 # ifdef _OPENMP
+
4288 # pragma omp parallel \
+
4289  default (none) \
+
4290  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubits,encoding, coeffs,exponents,numTerms, overrideInds,overridePhases,numOverrides, conj) \
+
4291  private (index, globalAmpInd, phaseInd, i,t,q, phase, c,s,re,im)
+
4292 # endif
+
4293  {
+
4294 # ifdef _OPENMP
+
4295 # pragma omp for schedule (static)
+
4296 # endif
+
4297  for (index=0LL; index<numAmps; index++) {
+
4298 
+
4299  // determine global amplitude index
+
4300  globalAmpInd = chunkId * numAmps + index;
+
4301 
+
4302  // determine phase index of {qubits}
+
4303  phaseInd = 0LL;
+
4304  if (encoding == UNSIGNED) {
+
4305  for (q=0; q<numQubits; q++) // use significance order specified by {qubits}
+
4306  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
4307  }
+
4308  else if (encoding == TWOS_COMPLEMENT) {
+
4309  for (q=0; q<numQubits-1; q++) // use final qubit to indicate sign
+
4310  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
4311  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
+
4312  phaseInd -= (1LL << (numQubits-1));
+
4313  }
+
4314 
+
4315  // determine if this phase index has an overriden value (i < numOverrides)
+
4316  for (i=0; i<numOverrides; i++)
+
4317  if (phaseInd == overrideInds[i])
+
4318  break;
+
4319 
+
4320  // determine phase from {coeffs}, {exponents} (unless overriden)
+
4321  phase = 0;
+
4322  if (i < numOverrides)
+
4323  phase = overridePhases[i];
+
4324  else
+
4325  for (t=0; t<numTerms; t++)
+
4326  phase += coeffs[t] * pow(phaseInd, exponents[t]);
+
4327 
+
4328  // negate phase to conjugate operator
+
4329  if (conj)
+
4330  phase *= -1;
+
4331 
+
4332  // modify amp to amp * exp(i phase)
+
4333  c = cos(phase);
+
4334  s = sin(phase);
+
4335  re = stateRe[index];
+
4336  im = stateIm[index];
+
4337 
+
4338  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4339  stateRe[index] = re*c - im*s;
+
4340  stateIm[index] = re*s + im*c;
+
4341  }
+
4342  }
+
4343 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, TWOS_COMPLEMENT, and UNSIGNED.

@@ -3688,53 +3693,53 @@

-

Definition at line 4084 of file QuEST_cpu.c.

-
4084  {
-
4085 
-
4086  qreal expecRe = 0;
-
4087  qreal expecIm = 0;
-
4088 
-
4089  long long int index;
-
4090  long long int numAmps = qureg.numAmpsPerChunk;
-
4091  qreal *stateReal = qureg.stateVec.real;
-
4092  qreal *stateImag = qureg.stateVec.imag;
-
4093  qreal *opReal = op.real;
-
4094  qreal *opImag = op.imag;
-
4095 
-
4096  qreal vecRe,vecIm,vecAbs, opRe, opIm;
-
4097 
-
4098 # ifdef _OPENMP
-
4099 # pragma omp parallel \
-
4100  shared (stateReal, stateImag, opReal, opImag, numAmps) \
-
4101  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
-
4102  reduction ( +:expecRe, expecIm )
-
4103 # endif
-
4104  {
-
4105 # ifdef _OPENMP
-
4106 # pragma omp for schedule (static)
-
4107 # endif
-
4108  for (index=0; index < numAmps; index++) {
-
4109  vecRe = stateReal[index];
-
4110  vecIm = stateImag[index];
-
4111  opRe = opReal[index];
-
4112  opIm = opImag[index];
-
4113 
-
4114  // abs(vec)^2 op
-
4115  vecAbs = vecRe*vecRe + vecIm*vecIm;
-
4116  expecRe += vecAbs*opRe;
-
4117  expecIm += vecAbs*opIm;
-
4118  }
-
4119  }
-
4120 
-
4121  Complex innerProd;
-
4122  innerProd.real = expecRe;
-
4123  innerProd.imag = expecIm;
-
4124  return innerProd;
-
4125 }
+

Definition at line 4124 of file QuEST_cpu.c.

+
4124  {
+
4125 
+
4126  qreal expecRe = 0;
+
4127  qreal expecIm = 0;
+
4128 
+
4129  long long int index;
+
4130  long long int numAmps = qureg.numAmpsPerChunk;
+
4131  qreal *stateReal = qureg.stateVec.real;
+
4132  qreal *stateImag = qureg.stateVec.imag;
+
4133  qreal *opReal = op.real;
+
4134  qreal *opImag = op.imag;
+
4135 
+
4136  qreal vecRe,vecIm,vecAbs, opRe, opIm;
+
4137 
+
4138 # ifdef _OPENMP
+
4139 # pragma omp parallel \
+
4140  shared (stateReal, stateImag, opReal, opImag, numAmps) \
+
4141  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
+
4142  reduction ( +:expecRe, expecIm )
+
4143 # endif
+
4144  {
+
4145 # ifdef _OPENMP
+
4146 # pragma omp for schedule (static)
+
4147 # endif
+
4148  for (index=0; index < numAmps; index++) {
+
4149  vecRe = stateReal[index];
+
4150  vecIm = stateImag[index];
+
4151  opRe = opReal[index];
+
4152  opIm = opImag[index];
+
4153 
+
4154  // abs(vec)^2 op
+
4155  vecAbs = vecRe*vecRe + vecIm*vecIm;
+
4156  expecRe += vecAbs*opRe;
+
4157  expecIm += vecAbs*opIm;
+
4158  }
+
4159  }
+
4160 
+
4161  Complex innerProd;
+
4162  innerProd.real = expecRe;
+
4163  innerProd.imag = expecIm;
+
4164  return innerProd;
+
4165 }

References Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

-

Referenced by statevec_calcExpecDiagonalOp().

+

Referenced by statevec_calcExpecDiagonalOp().

@@ -3764,48 +3769,48 @@

-

Definition at line 1071 of file QuEST_cpu.c.

-
1071  {
-
1072 
-
1073  qreal innerProdReal = 0;
-
1074  qreal innerProdImag = 0;
-
1075 
-
1076  long long int index;
-
1077  long long int numAmps = bra.numAmpsPerChunk;
-
1078  qreal *braVecReal = bra.stateVec.real;
-
1079  qreal *braVecImag = bra.stateVec.imag;
-
1080  qreal *ketVecReal = ket.stateVec.real;
-
1081  qreal *ketVecImag = ket.stateVec.imag;
-
1082 
-
1083  qreal braRe, braIm, ketRe, ketIm;
-
1084 
-
1085 # ifdef _OPENMP
-
1086 # pragma omp parallel \
-
1087  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
-
1088  private (index, braRe, braIm, ketRe, ketIm) \
-
1089  reduction ( +:innerProdReal, innerProdImag )
-
1090 # endif
-
1091  {
-
1092 # ifdef _OPENMP
-
1093 # pragma omp for schedule (static)
-
1094 # endif
-
1095  for (index=0; index < numAmps; index++) {
-
1096  braRe = braVecReal[index];
-
1097  braIm = braVecImag[index];
-
1098  ketRe = ketVecReal[index];
-
1099  ketIm = ketVecImag[index];
-
1100 
-
1101  // conj(bra_i) * ket_i
-
1102  innerProdReal += braRe*ketRe + braIm*ketIm;
-
1103  innerProdImag += braRe*ketIm - braIm*ketRe;
-
1104  }
-
1105  }
-
1106 
-
1107  Complex innerProd;
-
1108  innerProd.real = innerProdReal;
-
1109  innerProd.imag = innerProdImag;
-
1110  return innerProd;
-
1111 }
+

Definition at line 1082 of file QuEST_cpu.c.

+
1082  {
+
1083 
+
1084  qreal innerProdReal = 0;
+
1085  qreal innerProdImag = 0;
+
1086 
+
1087  long long int index;
+
1088  long long int numAmps = bra.numAmpsPerChunk;
+
1089  qreal *braVecReal = bra.stateVec.real;
+
1090  qreal *braVecImag = bra.stateVec.imag;
+
1091  qreal *ketVecReal = ket.stateVec.real;
+
1092  qreal *ketVecImag = ket.stateVec.imag;
+
1093 
+
1094  qreal braRe, braIm, ketRe, ketIm;
+
1095 
+
1096 # ifdef _OPENMP
+
1097 # pragma omp parallel \
+
1098  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
+
1099  private (index, braRe, braIm, ketRe, ketIm) \
+
1100  reduction ( +:innerProdReal, innerProdImag )
+
1101 # endif
+
1102  {
+
1103 # ifdef _OPENMP
+
1104 # pragma omp for schedule (static)
+
1105 # endif
+
1106  for (index=0; index < numAmps; index++) {
+
1107  braRe = braVecReal[index];
+
1108  braIm = braVecImag[index];
+
1109  ketRe = ketVecReal[index];
+
1110  ketIm = ketVecImag[index];
+
1111 
+
1112  // conj(bra_i) * ket_i
+
1113  innerProdReal += braRe*ketRe + braIm*ketIm;
+
1114  innerProdImag += braRe*ketIm - braIm*ketRe;
+
1115  }
+
1116  }
+
1117 
+
1118  Complex innerProd;
+
1119  innerProd.real = innerProdReal;
+
1120  innerProd.imag = innerProdImag;
+
1121  return innerProd;
+
1122 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

@@ -3851,76 +3856,77 @@

-

Definition at line 3510 of file QuEST_cpu.c.

-
3510  {
-
3511 
-
3512  /* Below, we manually reduce amplitudes into outcomeProbs by using atomic update.
-
3513  * This maintains OpenMP 3.1 compatibility. An alternative is to use array reduction
-
3514  * (requires OpenMP 4.5, limits #qubits since outcomeProbs must be a local stack array)
-
3515  * or a dynamic list of omp locks (duplicates memory cost of outcomeProbs).
-
3516  * Using locks was always slower than the method below. Using reduction was only
-
3517  * faster for very few threads, or very few outcomeProbs.
-
3518  */
-
3519 
-
3520  long long int numOutcomeProbs = (1 << numQubits);
-
3521  long long int j;
-
3522 
-
3523  // clear outcomeProbs (in parallel, in case it's large)
-
3524 # ifdef _OPENMP
-
3525 # pragma omp parallel \
-
3526  default (none) \
-
3527  shared (numOutcomeProbs,outcomeProbs) \
-
3528  private (j)
-
3529 # endif
-
3530  {
-
3531 # ifdef _OPENMP
-
3532 # pragma omp for schedule (static)
-
3533 # endif
-
3534  for (j=0; j<numOutcomeProbs; j++)
-
3535  outcomeProbs[j] = 0;
-
3536  }
-
3537 
-
3538  long long int numTasks = qureg.numAmpsPerChunk;
-
3539  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk;
-
3540  qreal* stateRe = qureg.stateVec.real;
-
3541  qreal* stateIm = qureg.stateVec.imag;
-
3542 
-
3543  long long int i;
-
3544  long long int outcomeInd;
-
3545  int q;
-
3546  qreal prob;
-
3547 
-
3548 # ifdef _OPENMP
-
3549 # pragma omp parallel \
-
3550  shared (numTasks,offset, qubits,numQubits, stateRe,stateIm, outcomeProbs) \
-
3551  private (i, q, outcomeInd, prob)
-
3552 # endif
-
3553  {
-
3554 # ifdef _OPENMP
-
3555 # pragma omp for schedule (static)
-
3556 # endif
-
3557  // every amplitude contributes to a single element of retProbs
-
3558  for (i=0; i<numTasks; i++) {
-
3559 
-
3560  // determine index informed by qubits outcome
-
3561  outcomeInd = 0;
-
3562  for (q=0; q<numQubits; q++)
-
3563  outcomeInd += extractBit(qubits[q], i + offset) * (1LL << q);
-
3564 
-
3565  prob = stateRe[i]*stateRe[i] + stateIm[i]*stateIm[i];
-
3566 
-
3567  // atomicly update corresponding outcome array element
-
3568  # ifdef _OPENMP
-
3569  # pragma omp atomic update
-
3570  # endif
-
3571  outcomeProbs[outcomeInd] += prob;
-
3572  }
-
3573  }
-
3574 }
+

Definition at line 3549 of file QuEST_cpu.c.

+
3549  {
+
3550 
+
3551  /* Below, we manually reduce amplitudes into outcomeProbs by using atomic update.
+
3552  * This maintains OpenMP 3.1 compatibility. An alternative is to use array reduction
+
3553  * (requires OpenMP 4.5, limits #qubits since outcomeProbs must be a local stack array)
+
3554  * or a dynamic list of omp locks (duplicates memory cost of outcomeProbs).
+
3555  * Using locks was always slower than the method below. Using reduction was only
+
3556  * faster for very few threads, or very few outcomeProbs.
+
3557  * Finally, we exclude the 'update' clause after 'atomic' to maintain MSVC compatibility
+
3558  */
+
3559 
+
3560  long long int numOutcomeProbs = (1 << numQubits);
+
3561  long long int j;
+
3562 
+
3563  // clear outcomeProbs (in parallel, in case it's large)
+
3564 # ifdef _OPENMP
+
3565 # pragma omp parallel \
+
3566  default (none) \
+
3567  shared (numOutcomeProbs,outcomeProbs) \
+
3568  private (j)
+
3569 # endif
+
3570  {
+
3571 # ifdef _OPENMP
+
3572 # pragma omp for schedule (static)
+
3573 # endif
+
3574  for (j=0; j<numOutcomeProbs; j++)
+
3575  outcomeProbs[j] = 0;
+
3576  }
+
3577 
+
3578  long long int numTasks = qureg.numAmpsPerChunk;
+
3579  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk;
+
3580  qreal* stateRe = qureg.stateVec.real;
+
3581  qreal* stateIm = qureg.stateVec.imag;
+
3582 
+
3583  long long int i;
+
3584  long long int outcomeInd;
+
3585  int q;
+
3586  qreal prob;
+
3587 
+
3588 # ifdef _OPENMP
+
3589 # pragma omp parallel \
+
3590  shared (numTasks,offset, qubits,numQubits, stateRe,stateIm, outcomeProbs) \
+
3591  private (i, q, outcomeInd, prob)
+
3592 # endif
+
3593  {
+
3594 # ifdef _OPENMP
+
3595 # pragma omp for schedule (static)
+
3596 # endif
+
3597  // every amplitude contributes to a single element of retProbs
+
3598  for (i=0; i<numTasks; i++) {
+
3599 
+
3600  // determine index informed by qubits outcome
+
3601  outcomeInd = 0;
+
3602  for (q=0; q<numQubits; q++)
+
3603  outcomeInd += extractBit(qubits[q], i + offset) * (1LL << q);
+
3604 
+
3605  prob = stateRe[i]*stateRe[i] + stateIm[i]*stateIm[i];
+
3606 
+
3607  // atomicly update corresponding outcome array element
+
3608  # ifdef _OPENMP
+
3609  # pragma omp atomic
+
3610  # endif
+
3611  outcomeProbs[outcomeInd] += prob;
+
3612  }
+
3613  }
+
3614 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_calcProbOfAllOutcomes().

+

Referenced by statevec_calcProbOfAllOutcomes().

@@ -3950,39 +3956,39 @@

-

Definition at line 1561 of file QuEST_cpu.c.

-
1561  {
-
1562 
-
1563  // registers are equal sized, so nodes hold the same state-vector partitions
-
1564  long long int stateVecSize;
-
1565  long long int index;
-
1566 
-
1567  // dimension of the state vector
-
1568  stateVecSize = targetQureg.numAmpsPerChunk;
-
1569 
-
1570  // Can't use qureg->stateVec as a private OMP var
-
1571  qreal *targetStateVecReal = targetQureg.stateVec.real;
-
1572  qreal *targetStateVecImag = targetQureg.stateVec.imag;
-
1573  qreal *copyStateVecReal = copyQureg.stateVec.real;
-
1574  qreal *copyStateVecImag = copyQureg.stateVec.imag;
-
1575 
-
1576  // initialise the state to |0000..0000>
-
1577 # ifdef _OPENMP
-
1578 # pragma omp parallel \
-
1579  default (none) \
-
1580  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
-
1581  private (index)
-
1582 # endif
-
1583  {
-
1584 # ifdef _OPENMP
-
1585 # pragma omp for schedule (static)
-
1586 # endif
-
1587  for (index=0; index<stateVecSize; index++) {
-
1588  targetStateVecReal[index] = copyStateVecReal[index];
-
1589  targetStateVecImag[index] = copyStateVecImag[index];
-
1590  }
-
1591  }
-
1592 }
+

Definition at line 1572 of file QuEST_cpu.c.

+
1572  {
+
1573 
+
1574  // registers are equal sized, so nodes hold the same state-vector partitions
+
1575  long long int stateVecSize;
+
1576  long long int index;
+
1577 
+
1578  // dimension of the state vector
+
1579  stateVecSize = targetQureg.numAmpsPerChunk;
+
1580 
+
1581  // Can't use qureg->stateVec as a private OMP var
+
1582  qreal *targetStateVecReal = targetQureg.stateVec.real;
+
1583  qreal *targetStateVecImag = targetQureg.stateVec.imag;
+
1584  qreal *copyStateVecReal = copyQureg.stateVec.real;
+
1585  qreal *copyStateVecImag = copyQureg.stateVec.imag;
+
1586 
+
1587  // initialise the state to |0000..0000>
+
1588 # ifdef _OPENMP
+
1589 # pragma omp parallel \
+
1590  default (none) \
+
1591  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
+
1592  private (index)
+
1593 # endif
+
1594  {
+
1595 # ifdef _OPENMP
+
1596 # pragma omp for schedule (static)
+
1597 # endif
+
1598  for (index=0; index<stateVecSize; index++) {
+
1599  targetStateVecReal[index] = copyStateVecReal[index];
+
1600  targetStateVecImag[index] = copyStateVecImag[index];
+
1601  }
+
1602  }
+
1603 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -4031,36 +4037,36 @@

Definition at line 3809 of file QuEST_cpu.c.

-
3810 {
-
3811  // ----- temp variables
-
3812  long long int thisTask;
-
3813  long long int numTasks=qureg.numAmpsPerChunk;
-
3814 
-
3815  qreal renorm=1/sqrt(totalProbability);
-
3816 
-
3817  qreal *stateVecReal = qureg.stateVec.real;
-
3818  qreal *stateVecImag = qureg.stateVec.imag;
-
3819 
-
3820 # ifdef _OPENMP
-
3821 # pragma omp parallel \
-
3822  shared (numTasks,stateVecReal,stateVecImag) \
-
3823  private (thisTask)
-
3824 # endif
-
3825  {
-
3826 # ifdef _OPENMP
-
3827 # pragma omp for schedule (static)
-
3828 # endif
-
3829  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3830  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
-
3831  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
-
3832  }
-
3833  }
-
3834 }
+

Definition at line 3849 of file QuEST_cpu.c.

+
3850 {
+
3851  // ----- temp variables
+
3852  long long int thisTask;
+
3853  long long int numTasks=qureg.numAmpsPerChunk;
+
3854 
+
3855  qreal renorm=1/sqrt(totalProbability);
+
3856 
+
3857  qreal *stateVecReal = qureg.stateVec.real;
+
3858  qreal *stateVecImag = qureg.stateVec.imag;
+
3859 
+
3860 # ifdef _OPENMP
+
3861 # pragma omp parallel \
+
3862  shared (numTasks,stateVecReal,stateVecImag) \
+
3863  private (thisTask)
+
3864 # endif
+
3865  {
+
3866 # ifdef _OPENMP
+
3867 # pragma omp for schedule (static)
+
3868 # endif
+
3869  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3870  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
+
3871  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
+
3872  }
+
3873  }
+
3874 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_collapseToKnownProbOutcome().

@@ -4114,76 +4120,76 @@

Definition at line 3727 of file QuEST_cpu.c.

-
3728 {
-
3729  // ----- sizes
-
3730  long long int sizeBlock, // size of blocks
-
3731  sizeHalfBlock; // size of blocks halved
-
3732  // ----- indices
-
3733  long long int thisBlock, // current block
-
3734  index; // current index for first half block
-
3735  // ----- measured probability
-
3736  qreal renorm; // probability (returned) value
-
3737  // ----- temp variables
-
3738  long long int thisTask; // task based approach for expose loop with small granularity
-
3739  // (good for shared memory parallelism)
-
3740  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3741 
-
3742  // ---------------------------------------------------------------- //
-
3743  // dimensions //
-
3744  // ---------------------------------------------------------------- //
-
3745  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3746  // and then the number to skip
-
3747  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3748 
-
3749  renorm=1/sqrt(totalProbability);
-
3750  qreal *stateVecReal = qureg.stateVec.real;
-
3751  qreal *stateVecImag = qureg.stateVec.imag;
-
3752 
-
3753 
-
3754 # ifdef _OPENMP
-
3755 # pragma omp parallel \
-
3756  default (none) \
-
3757  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
-
3758  private (thisTask,thisBlock,index)
-
3759 # endif
-
3760  {
-
3761  if (outcome==0){
-
3762  // measure qubit is 0
-
3763 # ifdef _OPENMP
-
3764 # pragma omp for schedule (static)
-
3765 # endif
-
3766  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3767  thisBlock = thisTask / sizeHalfBlock;
-
3768  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3769  stateVecReal[index]=stateVecReal[index]*renorm;
-
3770  stateVecImag[index]=stateVecImag[index]*renorm;
-
3771 
-
3772  stateVecReal[index+sizeHalfBlock]=0;
-
3773  stateVecImag[index+sizeHalfBlock]=0;
-
3774  }
-
3775  } else {
-
3776  // measure qubit is 1
-
3777 # ifdef _OPENMP
-
3778 # pragma omp for schedule (static)
-
3779 # endif
-
3780  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3781  thisBlock = thisTask / sizeHalfBlock;
-
3782  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3783  stateVecReal[index]=0;
-
3784  stateVecImag[index]=0;
-
3785 
-
3786  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
3787  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
3788  }
-
3789  }
-
3790  }
-
3791 
-
3792 }
+

Definition at line 3767 of file QuEST_cpu.c.

+
3768 {
+
3769  // ----- sizes
+
3770  long long int sizeBlock, // size of blocks
+
3771  sizeHalfBlock; // size of blocks halved
+
3772  // ----- indices
+
3773  long long int thisBlock, // current block
+
3774  index; // current index for first half block
+
3775  // ----- measured probability
+
3776  qreal renorm; // probability (returned) value
+
3777  // ----- temp variables
+
3778  long long int thisTask; // task based approach for expose loop with small granularity
+
3779  // (good for shared memory parallelism)
+
3780  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3781 
+
3782  // ---------------------------------------------------------------- //
+
3783  // dimensions //
+
3784  // ---------------------------------------------------------------- //
+
3785  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
3786  // and then the number to skip
+
3787  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
3788 
+
3789  renorm=1/sqrt(totalProbability);
+
3790  qreal *stateVecReal = qureg.stateVec.real;
+
3791  qreal *stateVecImag = qureg.stateVec.imag;
+
3792 
+
3793 
+
3794 # ifdef _OPENMP
+
3795 # pragma omp parallel \
+
3796  default (none) \
+
3797  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
+
3798  private (thisTask,thisBlock,index)
+
3799 # endif
+
3800  {
+
3801  if (outcome==0){
+
3802  // measure qubit is 0
+
3803 # ifdef _OPENMP
+
3804 # pragma omp for schedule (static)
+
3805 # endif
+
3806  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3807  thisBlock = thisTask / sizeHalfBlock;
+
3808  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3809  stateVecReal[index]=stateVecReal[index]*renorm;
+
3810  stateVecImag[index]=stateVecImag[index]*renorm;
+
3811 
+
3812  stateVecReal[index+sizeHalfBlock]=0;
+
3813  stateVecImag[index+sizeHalfBlock]=0;
+
3814  }
+
3815  } else {
+
3816  // measure qubit is 1
+
3817 # ifdef _OPENMP
+
3818 # pragma omp for schedule (static)
+
3819 # endif
+
3820  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3821  thisBlock = thisTask / sizeHalfBlock;
+
3822  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3823  stateVecReal[index]=0;
+
3824  stateVecImag[index]=0;
+
3825 
+
3826  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
+
3827  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
+
3828  }
+
3829  }
+
3830  }
+
3831 
+
3832 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_collapseToKnownProbOutcome().

@@ -4203,38 +4209,38 @@

-

Definition at line 3847 of file QuEST_cpu.c.

-
3848 {
-
3849  // ----- temp variables
-
3850  long long int thisTask;
-
3851  long long int numTasks=qureg.numAmpsPerChunk;
-
3852 
-
3853  // ---------------------------------------------------------------- //
-
3854  // find probability //
-
3855  // ---------------------------------------------------------------- //
-
3856 
-
3857  qreal *stateVecReal = qureg.stateVec.real;
-
3858  qreal *stateVecImag = qureg.stateVec.imag;
-
3859 
-
3860 # ifdef _OPENMP
-
3861 # pragma omp parallel \
-
3862  shared (numTasks,stateVecReal,stateVecImag) \
-
3863  private (thisTask)
-
3864 # endif
-
3865  {
-
3866 # ifdef _OPENMP
-
3867 # pragma omp for schedule (static)
-
3868 # endif
-
3869  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3870  stateVecReal[thisTask] = 0;
-
3871  stateVecImag[thisTask] = 0;
-
3872  }
-
3873  }
-
3874 }
+

Definition at line 3887 of file QuEST_cpu.c.

+
3888 {
+
3889  // ----- temp variables
+
3890  long long int thisTask;
+
3891  long long int numTasks=qureg.numAmpsPerChunk;
+
3892 
+
3893  // ---------------------------------------------------------------- //
+
3894  // find probability //
+
3895  // ---------------------------------------------------------------- //
+
3896 
+
3897  qreal *stateVecReal = qureg.stateVec.real;
+
3898  qreal *stateVecImag = qureg.stateVec.imag;
+
3899 
+
3900 # ifdef _OPENMP
+
3901 # pragma omp parallel \
+
3902  shared (numTasks,stateVecReal,stateVecImag) \
+
3903  private (thisTask)
+
3904 # endif
+
3905  {
+
3906 # ifdef _OPENMP
+
3907 # pragma omp for schedule (static)
+
3908 # endif
+
3909  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3910  stateVecReal[thisTask] = 0;
+
3911  stateVecImag[thisTask] = 0;
+
3912  }
+
3913  }
+
3914 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_collapseToKnownProbOutcome().

@@ -4301,48 +4307,48 @@

Definition at line 2056 of file QuEST_cpu.c.

-
2061 {
-
2062 
-
2063  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2064  long long int thisTask;
-
2065  long long int numTasks=qureg.numAmpsPerChunk;
-
2066 
-
2067  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2068  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2069  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2070  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2071  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2072 
-
2073 # ifdef _OPENMP
-
2074 # pragma omp parallel \
-
2075  default (none) \
-
2076  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2077  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
-
2078  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2079 # endif
-
2080  {
-
2081 # ifdef _OPENMP
-
2082 # pragma omp for schedule (static)
-
2083 # endif
-
2084  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2085  // store current state vector values in temp variables
-
2086  stateRealUp = stateVecRealUp[thisTask];
-
2087  stateImagUp = stateVecImagUp[thisTask];
-
2088 
-
2089  stateRealLo = stateVecRealLo[thisTask];
-
2090  stateImagLo = stateVecImagLo[thisTask];
-
2091 
-
2092  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2093  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2094  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2095  }
-
2096  }
-
2097 }
+

Definition at line 2095 of file QuEST_cpu.c.

+
2100 {
+
2101 
+
2102  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2103  long long int thisTask;
+
2104  long long int numTasks=qureg.numAmpsPerChunk;
+
2105 
+
2106  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2107  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2108  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2109  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2110  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2111 
+
2112 # ifdef _OPENMP
+
2113 # pragma omp parallel \
+
2114  default (none) \
+
2115  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2116  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
+
2117  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2118 # endif
+
2119  {
+
2120 # ifdef _OPENMP
+
2121 # pragma omp for schedule (static)
+
2122 # endif
+
2123  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2124  // store current state vector values in temp variables
+
2125  stateRealUp = stateVecRealUp[thisTask];
+
2126  stateImagUp = stateVecImagUp[thisTask];
+
2127 
+
2128  stateRealLo = stateVecRealLo[thisTask];
+
2129  stateImagLo = stateVecImagLo[thisTask];
+
2130 
+
2131  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2132  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
+
2133  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
+
2134  }
+
2135  }
+
2136 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_compactUnitary().

+

Referenced by statevec_compactUnitary().

@@ -4384,68 +4390,68 @@

-

Definition at line 1743 of file QuEST_cpu.c.

-
1744 {
-
1745  long long int sizeBlock, sizeHalfBlock;
-
1746  long long int thisBlock, // current block
-
1747  indexUp,indexLo; // current index and corresponding index in lower half block
-
1748 
-
1749  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1750  long long int thisTask;
-
1751  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1752 
-
1753  // set dimensions
-
1754  sizeHalfBlock = 1LL << targetQubit;
-
1755  sizeBlock = 2LL * sizeHalfBlock;
-
1756 
-
1757  // Can't use qureg.stateVec as a private OMP var
-
1758  qreal *stateVecReal = qureg.stateVec.real;
-
1759  qreal *stateVecImag = qureg.stateVec.imag;
-
1760  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
1761  qreal betaImag=beta.imag, betaReal=beta.real;
-
1762 
-
1763 # ifdef _OPENMP
-
1764 # pragma omp parallel \
-
1765  default (none) \
-
1766  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
-
1767  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1768 # endif
-
1769  {
-
1770 # ifdef _OPENMP
-
1771 # pragma omp for schedule (static)
-
1772 # endif
-
1773  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1774 
-
1775  thisBlock = thisTask / sizeHalfBlock;
-
1776  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1777  indexLo = indexUp + sizeHalfBlock;
-
1778 
-
1779  // store current state vector values in temp variables
-
1780  stateRealUp = stateVecReal[indexUp];
-
1781  stateImagUp = stateVecImag[indexUp];
-
1782 
-
1783  stateRealLo = stateVecReal[indexLo];
-
1784  stateImagLo = stateVecImag[indexLo];
+

Definition at line 1754 of file QuEST_cpu.c.

+
1755 {
+
1756  long long int sizeBlock, sizeHalfBlock;
+
1757  long long int thisBlock, // current block
+
1758  indexUp,indexLo; // current index and corresponding index in lower half block
+
1759 
+
1760  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
1761  long long int thisTask;
+
1762  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1763 
+
1764  // set dimensions
+
1765  sizeHalfBlock = 1LL << targetQubit;
+
1766  sizeBlock = 2LL * sizeHalfBlock;
+
1767 
+
1768  // Can't use qureg.stateVec as a private OMP var
+
1769  qreal *stateVecReal = qureg.stateVec.real;
+
1770  qreal *stateVecImag = qureg.stateVec.imag;
+
1771  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
1772  qreal betaImag=beta.imag, betaReal=beta.real;
+
1773 
+
1774 # ifdef _OPENMP
+
1775 # pragma omp parallel \
+
1776  default (none) \
+
1777  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
+
1778  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
1779 # endif
+
1780  {
+
1781 # ifdef _OPENMP
+
1782 # pragma omp for schedule (static)
+
1783 # endif
+
1784  for (thisTask=0; thisTask<numTasks; thisTask++) {
1785 
-
1786  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
1787  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
1788  - betaReal*stateRealLo - betaImag*stateImagLo;
-
1789  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
1790  - betaReal*stateImagLo + betaImag*stateRealLo;
-
1791 
-
1792  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
1793  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
1794  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
1795  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
1796  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
1797  }
-
1798  }
-
1799 
-
1800 }
+
1786  thisBlock = thisTask / sizeHalfBlock;
+
1787  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1788  indexLo = indexUp + sizeHalfBlock;
+
1789 
+
1790  // store current state vector values in temp variables
+
1791  stateRealUp = stateVecReal[indexUp];
+
1792  stateImagUp = stateVecImag[indexUp];
+
1793 
+
1794  stateRealLo = stateVecReal[indexLo];
+
1795  stateImagLo = stateVecImag[indexLo];
+
1796 
+
1797  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
1798  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
1799  - betaReal*stateRealLo - betaImag*stateImagLo;
+
1800  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
1801  - betaReal*stateImagLo + betaImag*stateRealLo;
+
1802 
+
1803  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
1804  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
1805  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
1806  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
1807  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
1808  }
+
1809  }
+
1810 
+
1811 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

-

Referenced by statevec_compactUnitary().

+

Referenced by statevec_compactUnitary().

@@ -4481,19 +4487,19 @@

-

Definition at line 1730 of file QuEST_cpu.c.

-
1730  {
-
1731  qreal diff;
-
1732  long long int chunkSize = mq1.numAmpsPerChunk;
-
1733 
-
1734  for (long long int i=0; i<chunkSize; i++){
-
1735  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
-
1736  if (diff>precision) return 0;
-
1737  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
-
1738  if (diff>precision) return 0;
-
1739  }
-
1740  return 1;
-
1741 }
+

Definition at line 1741 of file QuEST_cpu.c.

+
1741  {
+
1742  qreal diff;
+
1743  long long int chunkSize = mq1.numAmpsPerChunk;
+
1744 
+
1745  for (long long int i=0; i<chunkSize; i++){
+
1746  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
+
1747  if (diff>precision) return 0;
+
1748  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
+
1749  if (diff>precision) return 0;
+
1750  }
+
1751  return 1;
+
1752 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -4570,55 +4576,55 @@

Definition at line 2375 of file QuEST_cpu.c.

-
2380 {
-
2381 
-
2382  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2383  long long int thisTask;
-
2384  long long int numTasks=qureg.numAmpsPerChunk;
-
2385  long long int chunkSize=qureg.numAmpsPerChunk;
-
2386  long long int chunkId=qureg.chunkId;
-
2387 
-
2388  int controlBit;
-
2389 
-
2390  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2391  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2392  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2393  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2394  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2395 
-
2396 # ifdef _OPENMP
-
2397 # pragma omp parallel \
-
2398  default (none) \
-
2399  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2400  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
-
2401  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2402 # endif
-
2403  {
-
2404 # ifdef _OPENMP
-
2405 # pragma omp for schedule (static)
-
2406 # endif
-
2407  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2408  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2409  if (controlBit){
-
2410  // store current state vector values in temp variables
-
2411  stateRealUp = stateVecRealUp[thisTask];
-
2412  stateImagUp = stateVecImagUp[thisTask];
-
2413 
-
2414  stateRealLo = stateVecRealLo[thisTask];
-
2415  stateImagLo = stateVecImagLo[thisTask];
-
2416 
-
2417  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2418  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2419  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2420  }
-
2421  }
-
2422  }
-
2423 }
+

Definition at line 2414 of file QuEST_cpu.c.

+
2419 {
+
2420 
+
2421  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2422  long long int thisTask;
+
2423  long long int numTasks=qureg.numAmpsPerChunk;
+
2424  long long int chunkSize=qureg.numAmpsPerChunk;
+
2425  long long int chunkId=qureg.chunkId;
+
2426 
+
2427  int controlBit;
+
2428 
+
2429  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2430  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2431  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2432  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2433  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2434 
+
2435 # ifdef _OPENMP
+
2436 # pragma omp parallel \
+
2437  default (none) \
+
2438  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2439  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
+
2440  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2441 # endif
+
2442  {
+
2443 # ifdef _OPENMP
+
2444 # pragma omp for schedule (static)
+
2445 # endif
+
2446  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2447  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2448  if (controlBit){
+
2449  // store current state vector values in temp variables
+
2450  stateRealUp = stateVecRealUp[thisTask];
+
2451  stateImagUp = stateVecImagUp[thisTask];
+
2452 
+
2453  stateRealLo = stateVecRealLo[thisTask];
+
2454  stateImagLo = stateVecImagLo[thisTask];
+
2455 
+
2456  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2457  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
+
2458  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
+
2459  }
+
2460  }
+
2461  }
+
2462 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_controlledCompactUnitary().

+

Referenced by statevec_controlledCompactUnitary().

@@ -4666,76 +4672,76 @@

-

Definition at line 2157 of file QuEST_cpu.c.

-
2159 {
-
2160  long long int sizeBlock, sizeHalfBlock;
-
2161  long long int thisBlock, // current block
-
2162  indexUp,indexLo; // current index and corresponding index in lower half block
-
2163 
-
2164  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2165  long long int thisTask;
-
2166  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2167  long long int chunkSize=qureg.numAmpsPerChunk;
-
2168  long long int chunkId=qureg.chunkId;
-
2169 
-
2170  int controlBit;
-
2171 
-
2172  // set dimensions
-
2173  sizeHalfBlock = 1LL << targetQubit;
-
2174  sizeBlock = 2LL * sizeHalfBlock;
-
2175 
-
2176  // Can't use qureg.stateVec as a private OMP var
-
2177  qreal *stateVecReal = qureg.stateVec.real;
-
2178  qreal *stateVecImag = qureg.stateVec.imag;
-
2179  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
2180  qreal betaImag=beta.imag, betaReal=beta.real;
-
2181 
-
2182 # ifdef _OPENMP
-
2183 # pragma omp parallel \
-
2184  default (none) \
-
2185  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
-
2186  numTasks,chunkId,chunkSize,controlQubit) \
-
2187  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2188 # endif
-
2189  {
-
2190 # ifdef _OPENMP
-
2191 # pragma omp for schedule (static)
-
2192 # endif
-
2193  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2194 
-
2195  thisBlock = thisTask / sizeHalfBlock;
-
2196  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2197  indexLo = indexUp + sizeHalfBlock;
-
2198 
-
2199  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2200  if (controlBit){
-
2201  // store current state vector values in temp variables
-
2202  stateRealUp = stateVecReal[indexUp];
-
2203  stateImagUp = stateVecImag[indexUp];
-
2204 
-
2205  stateRealLo = stateVecReal[indexLo];
-
2206  stateImagLo = stateVecImag[indexLo];
-
2207 
-
2208  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2209  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
2210  - betaReal*stateRealLo - betaImag*stateImagLo;
-
2211  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
2212  - betaReal*stateImagLo + betaImag*stateRealLo;
-
2213 
-
2214  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
2215  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
2216  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
2217  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
2218  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
2219  }
-
2220  }
-
2221  }
-
2222 
-
2223 }
+

Definition at line 2196 of file QuEST_cpu.c.

+
2198 {
+
2199  long long int sizeBlock, sizeHalfBlock;
+
2200  long long int thisBlock, // current block
+
2201  indexUp,indexLo; // current index and corresponding index in lower half block
+
2202 
+
2203  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2204  long long int thisTask;
+
2205  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2206  long long int chunkSize=qureg.numAmpsPerChunk;
+
2207  long long int chunkId=qureg.chunkId;
+
2208 
+
2209  int controlBit;
+
2210 
+
2211  // set dimensions
+
2212  sizeHalfBlock = 1LL << targetQubit;
+
2213  sizeBlock = 2LL * sizeHalfBlock;
+
2214 
+
2215  // Can't use qureg.stateVec as a private OMP var
+
2216  qreal *stateVecReal = qureg.stateVec.real;
+
2217  qreal *stateVecImag = qureg.stateVec.imag;
+
2218  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
2219  qreal betaImag=beta.imag, betaReal=beta.real;
+
2220 
+
2221 # ifdef _OPENMP
+
2222 # pragma omp parallel \
+
2223  default (none) \
+
2224  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
+
2225  numTasks,chunkId,chunkSize,controlQubit) \
+
2226  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2227 # endif
+
2228  {
+
2229 # ifdef _OPENMP
+
2230 # pragma omp for schedule (static)
+
2231 # endif
+
2232  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2233 
+
2234  thisBlock = thisTask / sizeHalfBlock;
+
2235  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2236  indexLo = indexUp + sizeHalfBlock;
+
2237 
+
2238  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
+
2239  if (controlBit){
+
2240  // store current state vector values in temp variables
+
2241  stateRealUp = stateVecReal[indexUp];
+
2242  stateImagUp = stateVecImag[indexUp];
+
2243 
+
2244  stateRealLo = stateVecReal[indexLo];
+
2245  stateImagLo = stateVecImag[indexLo];
+
2246 
+
2247  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2248  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
2249  - betaReal*stateRealLo - betaImag*stateImagLo;
+
2250  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
2251  - betaReal*stateImagLo + betaImag*stateRealLo;
+
2252 
+
2253  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
2254  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
2255  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
2256  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
2257  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
2258  }
+
2259  }
+
2260  }
+
2261 
+
2262 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

-

Referenced by statevec_controlledCompactUnitary().

+

Referenced by statevec_controlledCompactUnitary().

@@ -4789,43 +4795,43 @@

Definition at line 2703 of file QuEST_cpu.c.

-
2706 {
-
2707 
-
2708  long long int thisTask;
-
2709  long long int numTasks=qureg.numAmpsPerChunk;
-
2710  long long int chunkSize=qureg.numAmpsPerChunk;
-
2711  long long int chunkId=qureg.chunkId;
-
2712 
-
2713  int controlBit;
-
2714 
-
2715  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2716  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2717 
-
2718 # ifdef _OPENMP
-
2719 # pragma omp parallel \
-
2720  default (none) \
-
2721  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2722  numTasks,chunkId,chunkSize,controlQubit) \
-
2723  private (thisTask,controlBit)
-
2724 # endif
-
2725  {
-
2726 # ifdef _OPENMP
-
2727 # pragma omp for schedule (static)
-
2728 # endif
-
2729  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2730  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2731  if (controlBit){
-
2732  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2733  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2734  }
-
2735  }
-
2736  }
-
2737 }
+

Definition at line 2742 of file QuEST_cpu.c.

+
2745 {
+
2746 
+
2747  long long int thisTask;
+
2748  long long int numTasks=qureg.numAmpsPerChunk;
+
2749  long long int chunkSize=qureg.numAmpsPerChunk;
+
2750  long long int chunkId=qureg.chunkId;
+
2751 
+
2752  int controlBit;
+
2753 
+
2754  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2755  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2756 
+
2757 # ifdef _OPENMP
+
2758 # pragma omp parallel \
+
2759  default (none) \
+
2760  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
2761  numTasks,chunkId,chunkSize,controlQubit) \
+
2762  private (thisTask,controlBit)
+
2763 # endif
+
2764  {
+
2765 # ifdef _OPENMP
+
2766 # pragma omp for schedule (static)
+
2767 # endif
+
2768  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2769  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2770  if (controlBit){
+
2771  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
+
2772  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
+
2773  }
+
2774  }
+
2775  }
+
2776 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_controlledNot().

+

Referenced by statevec_controlledNot().

@@ -4861,61 +4867,61 @@

-

Definition at line 2640 of file QuEST_cpu.c.

-
2641 {
-
2642  long long int sizeBlock, sizeHalfBlock;
-
2643  long long int thisBlock, // current block
-
2644  indexUp,indexLo; // current index and corresponding index in lower half block
-
2645 
-
2646  qreal stateRealUp,stateImagUp;
-
2647  long long int thisTask;
-
2648  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2649  long long int chunkSize=qureg.numAmpsPerChunk;
-
2650  long long int chunkId=qureg.chunkId;
-
2651 
-
2652  int controlBit;
-
2653 
-
2654  // set dimensions
-
2655  sizeHalfBlock = 1LL << targetQubit;
-
2656  sizeBlock = 2LL * sizeHalfBlock;
-
2657 
-
2658  // Can't use qureg.stateVec as a private OMP var
-
2659  qreal *stateVecReal = qureg.stateVec.real;
-
2660  qreal *stateVecImag = qureg.stateVec.imag;
-
2661 
-
2662 # ifdef _OPENMP
-
2663 # pragma omp parallel \
-
2664  default (none) \
-
2665  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
-
2666  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2667 # endif
-
2668  {
-
2669 # ifdef _OPENMP
-
2670 # pragma omp for schedule (static)
-
2671 # endif
-
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2673  thisBlock = thisTask / sizeHalfBlock;
-
2674  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2675  indexLo = indexUp + sizeHalfBlock;
-
2676 
-
2677  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2678  if (controlBit){
-
2679  stateRealUp = stateVecReal[indexUp];
-
2680  stateImagUp = stateVecImag[indexUp];
-
2681 
-
2682  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2683  stateVecImag[indexUp] = stateVecImag[indexLo];
+

Definition at line 2679 of file QuEST_cpu.c.

+
2680 {
+
2681  long long int sizeBlock, sizeHalfBlock;
+
2682  long long int thisBlock, // current block
+
2683  indexUp,indexLo; // current index and corresponding index in lower half block
2684 
-
2685  stateVecReal[indexLo] = stateRealUp;
-
2686  stateVecImag[indexLo] = stateImagUp;
-
2687  }
-
2688  }
-
2689  }
-
2690 }
+
2685  qreal stateRealUp,stateImagUp;
+
2686  long long int thisTask;
+
2687  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2688  long long int chunkSize=qureg.numAmpsPerChunk;
+
2689  long long int chunkId=qureg.chunkId;
+
2690 
+
2691  int controlBit;
+
2692 
+
2693  // set dimensions
+
2694  sizeHalfBlock = 1LL << targetQubit;
+
2695  sizeBlock = 2LL * sizeHalfBlock;
+
2696 
+
2697  // Can't use qureg.stateVec as a private OMP var
+
2698  qreal *stateVecReal = qureg.stateVec.real;
+
2699  qreal *stateVecImag = qureg.stateVec.imag;
+
2700 
+
2701 # ifdef _OPENMP
+
2702 # pragma omp parallel \
+
2703  default (none) \
+
2704  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
+
2705  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
2706 # endif
+
2707  {
+
2708 # ifdef _OPENMP
+
2709 # pragma omp for schedule (static)
+
2710 # endif
+
2711  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2712  thisBlock = thisTask / sizeHalfBlock;
+
2713  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2714  indexLo = indexUp + sizeHalfBlock;
+
2715 
+
2716  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
+
2717  if (controlBit){
+
2718  stateRealUp = stateVecReal[indexUp];
+
2719  stateImagUp = stateVecImag[indexUp];
+
2720 
+
2721  stateVecReal[indexUp] = stateVecReal[indexLo];
+
2722  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2723 
+
2724  stateVecReal[indexLo] = stateRealUp;
+
2725  stateVecImag[indexLo] = stateImagUp;
+
2726  }
+
2727  }
+
2728  }
+
2729 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_controlledNot().

+

Referenced by statevec_controlledNot().

@@ -4963,43 +4969,43 @@

-

Definition at line 2997 of file QuEST_cpu.c.

-
3000 {
-
3001 
-
3002  long long int thisTask;
-
3003  long long int numTasks=qureg.numAmpsPerChunk;
-
3004  long long int chunkSize=qureg.numAmpsPerChunk;
-
3005  long long int chunkId=qureg.chunkId;
-
3006 
-
3007  int controlBit;
-
3008 
-
3009  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
3010  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
3011 
-
3012 # ifdef _OPENMP
-
3013 # pragma omp parallel \
-
3014  default (none) \
-
3015  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
3016  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
-
3017  private (thisTask,controlBit)
-
3018 # endif
-
3019  {
-
3020 # ifdef _OPENMP
-
3021 # pragma omp for schedule (static)
-
3022 # endif
-
3023  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3024  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
3025  if (controlBit){
-
3026  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
-
3027  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
-
3028  }
-
3029  }
-
3030  }
-
3031 }
+

Definition at line 3036 of file QuEST_cpu.c.

+
3039 {
+
3040 
+
3041  long long int thisTask;
+
3042  long long int numTasks=qureg.numAmpsPerChunk;
+
3043  long long int chunkSize=qureg.numAmpsPerChunk;
+
3044  long long int chunkId=qureg.chunkId;
+
3045 
+
3046  int controlBit;
+
3047 
+
3048  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
3049  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
3050 
+
3051 # ifdef _OPENMP
+
3052 # pragma omp parallel \
+
3053  default (none) \
+
3054  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
3055  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
+
3056  private (thisTask,controlBit)
+
3057 # endif
+
3058  {
+
3059 # ifdef _OPENMP
+
3060 # pragma omp for schedule (static)
+
3061 # endif
+
3062  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3063  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
3064  if (controlBit){
+
3065  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
+
3066  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
+
3067  }
+
3068  }
+
3069  }
+
3070 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

+

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

@@ -5041,62 +5047,62 @@

-

Definition at line 2943 of file QuEST_cpu.c.

-
2944 {
-
2945  long long int sizeBlock, sizeHalfBlock;
-
2946  long long int thisBlock, // current block
-
2947  indexUp,indexLo; // current index and corresponding index in lower half block
-
2948 
-
2949  qreal stateRealUp,stateImagUp;
-
2950  long long int thisTask;
-
2951  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2952  long long int chunkSize=qureg.numAmpsPerChunk;
-
2953  long long int chunkId=qureg.chunkId;
-
2954 
-
2955  int controlBit;
-
2956 
-
2957  // set dimensions
-
2958  sizeHalfBlock = 1LL << targetQubit;
-
2959  sizeBlock = 2LL * sizeHalfBlock;
-
2960 
-
2961  // Can't use qureg.stateVec as a private OMP var
-
2962  qreal *stateVecReal = qureg.stateVec.real;
-
2963  qreal *stateVecImag = qureg.stateVec.imag;
-
2964 
-
2965 # ifdef _OPENMP
-
2966 # pragma omp parallel \
-
2967  default (none) \
-
2968  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
-
2969  chunkSize,controlQubit,conjFac) \
-
2970  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2971 # endif
-
2972  {
-
2973 # ifdef _OPENMP
-
2974 # pragma omp for schedule (static)
-
2975 # endif
-
2976  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2977  thisBlock = thisTask / sizeHalfBlock;
-
2978  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2979  indexLo = indexUp + sizeHalfBlock;
-
2980 
-
2981  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2982  if (controlBit){
-
2983  stateRealUp = stateVecReal[indexUp];
-
2984  stateImagUp = stateVecImag[indexUp];
-
2985 
-
2986  // update under +-{{0, -i}, {i, 0}}
-
2987  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2988  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2989  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2990  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2991  }
-
2992  }
-
2993  }
-
2994 }
+

Definition at line 2982 of file QuEST_cpu.c.

+
2983 {
+
2984  long long int sizeBlock, sizeHalfBlock;
+
2985  long long int thisBlock, // current block
+
2986  indexUp,indexLo; // current index and corresponding index in lower half block
+
2987 
+
2988  qreal stateRealUp,stateImagUp;
+
2989  long long int thisTask;
+
2990  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2991  long long int chunkSize=qureg.numAmpsPerChunk;
+
2992  long long int chunkId=qureg.chunkId;
+
2993 
+
2994  int controlBit;
+
2995 
+
2996  // set dimensions
+
2997  sizeHalfBlock = 1LL << targetQubit;
+
2998  sizeBlock = 2LL * sizeHalfBlock;
+
2999 
+
3000  // Can't use qureg.stateVec as a private OMP var
+
3001  qreal *stateVecReal = qureg.stateVec.real;
+
3002  qreal *stateVecImag = qureg.stateVec.imag;
+
3003 
+
3004 # ifdef _OPENMP
+
3005 # pragma omp parallel \
+
3006  default (none) \
+
3007  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
+
3008  chunkSize,controlQubit,conjFac) \
+
3009  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
3010 # endif
+
3011  {
+
3012 # ifdef _OPENMP
+
3013 # pragma omp for schedule (static)
+
3014 # endif
+
3015  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3016  thisBlock = thisTask / sizeHalfBlock;
+
3017  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3018  indexLo = indexUp + sizeHalfBlock;
+
3019 
+
3020  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
+
3021  if (controlBit){
+
3022  stateRealUp = stateVecReal[indexUp];
+
3023  stateImagUp = stateVecImag[indexUp];
+
3024 
+
3025  // update under +-{{0, -i}, {i, 0}}
+
3026  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
3027  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
3028  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
3029  stateVecImag[indexLo] = conjFac * stateRealUp;
+
3030  }
+
3031  }
+
3032  }
+
3033 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

+

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

@@ -5132,36 +5138,36 @@

-

Definition at line 3647 of file QuEST_cpu.c.

-
3648 {
-
3649  long long int index;
-
3650  long long int stateVecSize;
-
3651  int bit1, bit2;
-
3652 
-
3653  long long int chunkSize=qureg.numAmpsPerChunk;
-
3654  long long int chunkId=qureg.chunkId;
-
3655 
-
3656  // dimension of the state vector
-
3657  stateVecSize = qureg.numAmpsPerChunk;
-
3658  qreal *stateVecReal = qureg.stateVec.real;
-
3659  qreal *stateVecImag = qureg.stateVec.imag;
-
3660 
-
3661 # ifdef _OPENMP
-
3662 # pragma omp parallel for \
-
3663  default (none) \
-
3664  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
-
3665  private (index,bit1,bit2) \
-
3666  schedule (static)
-
3667 # endif
-
3668  for (index=0; index<stateVecSize; index++) {
-
3669  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3670  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3671  if (bit1 && bit2) {
-
3672  stateVecReal [index] = - stateVecReal [index];
-
3673  stateVecImag [index] = - stateVecImag [index];
-
3674  }
-
3675  }
-
3676 }
+

Definition at line 3687 of file QuEST_cpu.c.

+
3688 {
+
3689  long long int index;
+
3690  long long int stateVecSize;
+
3691  int bit1, bit2;
+
3692 
+
3693  long long int chunkSize=qureg.numAmpsPerChunk;
+
3694  long long int chunkId=qureg.chunkId;
+
3695 
+
3696  // dimension of the state vector
+
3697  stateVecSize = qureg.numAmpsPerChunk;
+
3698  qreal *stateVecReal = qureg.stateVec.real;
+
3699  qreal *stateVecImag = qureg.stateVec.imag;
+
3700 
+
3701 # ifdef _OPENMP
+
3702 # pragma omp parallel for \
+
3703  default (none) \
+
3704  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
+
3705  private (index,bit1,bit2) \
+
3706  schedule (static)
+
3707 # endif
+
3708  for (index=0; index<stateVecSize; index++) {
+
3709  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
+
3710  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
+
3711  if (bit1 && bit2) {
+
3712  stateVecReal [index] = - stateVecReal [index];
+
3713  stateVecImag [index] = - stateVecImag [index];
+
3714  }
+
3715  }
+
3716 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -5205,45 +5211,45 @@

-

Definition at line 3187 of file QuEST_cpu.c.

-
3188 {
-
3189  long long int index;
-
3190  long long int stateVecSize;
-
3191  int bit1, bit2;
-
3192 
-
3193  long long int chunkSize=qureg.numAmpsPerChunk;
-
3194  long long int chunkId=qureg.chunkId;
-
3195 
-
3196  // dimension of the state vector
-
3197  stateVecSize = qureg.numAmpsPerChunk;
-
3198  qreal *stateVecReal = qureg.stateVec.real;
-
3199  qreal *stateVecImag = qureg.stateVec.imag;
-
3200 
-
3201  qreal stateRealLo, stateImagLo;
-
3202  qreal cosAngle = cos(angle);
-
3203  qreal sinAngle = sin(angle);
-
3204 
-
3205 # ifdef _OPENMP
-
3206 # pragma omp parallel for \
-
3207  default (none) \
-
3208  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
-
3209  idQubit1,idQubit2,cosAngle,sinAngle ) \
-
3210  private (index,bit1,bit2,stateRealLo,stateImagLo) \
-
3211  schedule (static)
-
3212 # endif
-
3213  for (index=0; index<stateVecSize; index++) {
-
3214  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3215  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3216  if (bit1 && bit2) {
-
3217 
-
3218  stateRealLo = stateVecReal[index];
-
3219  stateImagLo = stateVecImag[index];
-
3220 
-
3221  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3222  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3223  }
-
3224  }
-
3225 }
+

Definition at line 3226 of file QuEST_cpu.c.

+
3227 {
+
3228  long long int index;
+
3229  long long int stateVecSize;
+
3230  int bit1, bit2;
+
3231 
+
3232  long long int chunkSize=qureg.numAmpsPerChunk;
+
3233  long long int chunkId=qureg.chunkId;
+
3234 
+
3235  // dimension of the state vector
+
3236  stateVecSize = qureg.numAmpsPerChunk;
+
3237  qreal *stateVecReal = qureg.stateVec.real;
+
3238  qreal *stateVecImag = qureg.stateVec.imag;
+
3239 
+
3240  qreal stateRealLo, stateImagLo;
+
3241  qreal cosAngle = cos(angle);
+
3242  qreal sinAngle = sin(angle);
+
3243 
+
3244 # ifdef _OPENMP
+
3245 # pragma omp parallel for \
+
3246  default (none) \
+
3247  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
+
3248  idQubit1,idQubit2,cosAngle,sinAngle ) \
+
3249  private (index,bit1,bit2,stateRealLo,stateImagLo) \
+
3250  schedule (static)
+
3251 # endif
+
3252  for (index=0; index<stateVecSize; index++) {
+
3253  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
+
3254  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
+
3255  if (bit1 && bit2) {
+
3256 
+
3257  stateRealLo = stateVecReal[index];
+
3258  stateImagLo = stateVecImag[index];
+
3259 
+
3260  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3261  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3262  }
+
3263  }
+
3264 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -5320,56 +5326,56 @@

Definition at line 2437 of file QuEST_cpu.c.

-
2442 {
-
2443 
-
2444  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2445  long long int thisTask;
-
2446  long long int numTasks=qureg.numAmpsPerChunk;
-
2447  long long int chunkSize=qureg.numAmpsPerChunk;
-
2448  long long int chunkId=qureg.chunkId;
-
2449 
-
2450  int controlBit;
-
2451 
-
2452  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2453  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2454  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2455  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2456  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2457 
-
2458 # ifdef _OPENMP
-
2459 # pragma omp parallel \
-
2460  default (none) \
-
2461  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2462  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
-
2463  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2464 # endif
-
2465  {
-
2466 # ifdef _OPENMP
-
2467 # pragma omp for schedule (static)
-
2468 # endif
-
2469  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2470  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2471  if (controlBit){
-
2472  // store current state vector values in temp variables
-
2473  stateRealUp = stateVecRealUp[thisTask];
-
2474  stateImagUp = stateVecImagUp[thisTask];
-
2475 
-
2476  stateRealLo = stateVecRealLo[thisTask];
-
2477  stateImagLo = stateVecImagLo[thisTask];
-
2478 
-
2479  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2480  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2481  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2482  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2483  }
-
2484  }
-
2485  }
-
2486 }
+

Definition at line 2476 of file QuEST_cpu.c.

+
2481 {
+
2482 
+
2483  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2484  long long int thisTask;
+
2485  long long int numTasks=qureg.numAmpsPerChunk;
+
2486  long long int chunkSize=qureg.numAmpsPerChunk;
+
2487  long long int chunkId=qureg.chunkId;
+
2488 
+
2489  int controlBit;
+
2490 
+
2491  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2492  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2493  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2494  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2495  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2496 
+
2497 # ifdef _OPENMP
+
2498 # pragma omp parallel \
+
2499  default (none) \
+
2500  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2501  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
+
2502  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2503 # endif
+
2504  {
+
2505 # ifdef _OPENMP
+
2506 # pragma omp for schedule (static)
+
2507 # endif
+
2508  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2509  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2510  if (controlBit){
+
2511  // store current state vector values in temp variables
+
2512  stateRealUp = stateVecRealUp[thisTask];
+
2513  stateImagUp = stateVecImagUp[thisTask];
+
2514 
+
2515  stateRealLo = stateVecRealLo[thisTask];
+
2516  stateImagLo = stateVecImagLo[thisTask];
+
2517 
+
2518  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2519  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2520  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2521  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2522  }
+
2523  }
+
2524  }
+
2525 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_controlledUnitary().

+

Referenced by statevec_controlledUnitary().

@@ -5411,74 +5417,74 @@

-

Definition at line 2297 of file QuEST_cpu.c.

-
2299 {
-
2300  long long int sizeBlock, sizeHalfBlock;
-
2301  long long int thisBlock, // current block
-
2302  indexUp,indexLo; // current index and corresponding index in lower half block
-
2303 
-
2304  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2305  long long int thisTask;
-
2306  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2307  long long int chunkSize=qureg.numAmpsPerChunk;
-
2308  long long int chunkId=qureg.chunkId;
-
2309 
-
2310  int controlBit;
-
2311 
-
2312  // set dimensions
-
2313  sizeHalfBlock = 1LL << targetQubit;
-
2314  sizeBlock = 2LL * sizeHalfBlock;
-
2315 
-
2316  // Can't use qureg.stateVec as a private OMP var
-
2317  qreal *stateVecReal = qureg.stateVec.real;
-
2318  qreal *stateVecImag = qureg.stateVec.imag;
-
2319 
-
2320 # ifdef _OPENMP
-
2321 # pragma omp parallel \
-
2322  default (none) \
-
2323  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
-
2324  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2325 # endif
-
2326  {
-
2327 # ifdef _OPENMP
-
2328 # pragma omp for schedule (static)
-
2329 # endif
-
2330  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2331 
-
2332  thisBlock = thisTask / sizeHalfBlock;
-
2333  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2334  indexLo = indexUp + sizeHalfBlock;
-
2335 
-
2336  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2337  if (controlBit){
-
2338  // store current state vector values in temp variables
-
2339  stateRealUp = stateVecReal[indexUp];
-
2340  stateImagUp = stateVecImag[indexUp];
-
2341 
-
2342  stateRealLo = stateVecReal[indexLo];
-
2343  stateImagLo = stateVecImag[indexLo];
-
2344 
-
2345 
-
2346  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2347  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2348  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2349  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2350  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2351 
-
2352  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2353  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2354  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2355  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2356  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2357  }
-
2358  }
-
2359  }
-
2360 
-
2361 }
+

Definition at line 2336 of file QuEST_cpu.c.

+
2338 {
+
2339  long long int sizeBlock, sizeHalfBlock;
+
2340  long long int thisBlock, // current block
+
2341  indexUp,indexLo; // current index and corresponding index in lower half block
+
2342 
+
2343  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2344  long long int thisTask;
+
2345  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2346  long long int chunkSize=qureg.numAmpsPerChunk;
+
2347  long long int chunkId=qureg.chunkId;
+
2348 
+
2349  int controlBit;
+
2350 
+
2351  // set dimensions
+
2352  sizeHalfBlock = 1LL << targetQubit;
+
2353  sizeBlock = 2LL * sizeHalfBlock;
+
2354 
+
2355  // Can't use qureg.stateVec as a private OMP var
+
2356  qreal *stateVecReal = qureg.stateVec.real;
+
2357  qreal *stateVecImag = qureg.stateVec.imag;
+
2358 
+
2359 # ifdef _OPENMP
+
2360 # pragma omp parallel \
+
2361  default (none) \
+
2362  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
+
2363  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2364 # endif
+
2365  {
+
2366 # ifdef _OPENMP
+
2367 # pragma omp for schedule (static)
+
2368 # endif
+
2369  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2370 
+
2371  thisBlock = thisTask / sizeHalfBlock;
+
2372  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2373  indexLo = indexUp + sizeHalfBlock;
+
2374 
+
2375  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
+
2376  if (controlBit){
+
2377  // store current state vector values in temp variables
+
2378  stateRealUp = stateVecReal[indexUp];
+
2379  stateImagUp = stateVecImag[indexUp];
+
2380 
+
2381  stateRealLo = stateVecReal[indexLo];
+
2382  stateImagLo = stateVecImag[indexLo];
+
2383 
+
2384 
+
2385  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2386  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2387  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2388  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2389  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2390 
+
2391  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2392  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2393  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2394  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2395  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2396  }
+
2397  }
+
2398  }
+
2399 
+
2400 }

References Qureg::chunkId, extractBit(), ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

-

Referenced by statevec_controlledUnitary().

+

Referenced by statevec_controlledUnitary().

@@ -5514,45 +5520,45 @@

-

Definition at line 1279 of file QuEST_cpu.c.

-
1280 {
-
1281  long long int numAmps = 1LL << numQubits;
-
1282  long long int numAmpsPerRank = numAmps/env.numRanks;
-
1283 
-
1284  if (numAmpsPerRank > SIZE_MAX) {
-
1285  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
-
1286  exit (EXIT_FAILURE);
-
1287  }
-
1288 
-
1289  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
-
1290  qureg->stateVec.real = malloc(arrSize);
-
1291  qureg->stateVec.imag = malloc(arrSize);
-
1292  if (env.numRanks>1){
-
1293  qureg->pairStateVec.real = malloc(arrSize);
-
1294  qureg->pairStateVec.imag = malloc(arrSize);
-
1295  }
-
1296 
-
1297  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
1298  && numAmpsPerRank ) {
-
1299  printf("Could not allocate memory!");
-
1300  exit (EXIT_FAILURE);
-
1301  }
-
1302 
-
1303  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
1304  && numAmpsPerRank ) {
-
1305  printf("Could not allocate memory!");
-
1306  exit (EXIT_FAILURE);
-
1307  }
-
1308 
-
1309  qureg->numQubitsInStateVec = numQubits;
-
1310  qureg->numAmpsTotal = numAmps;
-
1311  qureg->numAmpsPerChunk = numAmpsPerRank;
-
1312  qureg->chunkId = env.rank;
-
1313  qureg->numChunks = env.numRanks;
-
1314  qureg->isDensityMatrix = 0;
-
1315 }
+

Definition at line 1290 of file QuEST_cpu.c.

+
1291 {
+
1292  long long int numAmps = 1LL << numQubits;
+
1293  long long int numAmpsPerRank = numAmps/env.numRanks;
+
1294 
+
1295  if (numAmpsPerRank > SIZE_MAX) {
+
1296  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
+
1297  exit (EXIT_FAILURE);
+
1298  }
+
1299 
+
1300  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
+
1301  qureg->stateVec.real = malloc(arrSize);
+
1302  qureg->stateVec.imag = malloc(arrSize);
+
1303  if (env.numRanks>1){
+
1304  qureg->pairStateVec.real = malloc(arrSize);
+
1305  qureg->pairStateVec.imag = malloc(arrSize);
+
1306  }
+
1307 
+
1308  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
+
1309  && numAmpsPerRank ) {
+
1310  printf("Could not allocate memory!");
+
1311  exit (EXIT_FAILURE);
+
1312  }
+
1313 
+
1314  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
+
1315  && numAmpsPerRank ) {
+
1316  printf("Could not allocate memory!");
+
1317  exit (EXIT_FAILURE);
+
1318  }
+
1319 
+
1320  qureg->numQubitsInStateVec = numQubits;
+
1321  qureg->numAmpsTotal = numAmps;
+
1322  qureg->numAmpsPerChunk = numAmpsPerRank;
+
1323  qureg->chunkId = env.rank;
+
1324  qureg->numChunks = env.numRanks;
+
1325  qureg->isDensityMatrix = 0;
+
1326 }
-

References Qureg::chunkId, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, QuESTEnv::rank, and Qureg::stateVec.

+

References Qureg::chunkId, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, QuESTEnv::rank, and Qureg::stateVec.

@@ -5582,26 +5588,26 @@

-

Definition at line 1317 of file QuEST_cpu.c.

-
1317  {
-
1318 
-
1319  qureg.numQubitsInStateVec = 0;
-
1320  qureg.numAmpsTotal = 0;
-
1321  qureg.numAmpsPerChunk = 0;
-
1322 
-
1323  free(qureg.stateVec.real);
-
1324  free(qureg.stateVec.imag);
-
1325  if (env.numRanks>1){
-
1326  free(qureg.pairStateVec.real);
-
1327  free(qureg.pairStateVec.imag);
-
1328  }
-
1329  qureg.stateVec.real = NULL;
-
1330  qureg.stateVec.imag = NULL;
-
1331  qureg.pairStateVec.real = NULL;
-
1332  qureg.pairStateVec.imag = NULL;
-
1333 }
+

Definition at line 1328 of file QuEST_cpu.c.

+
1328  {
+
1329 
+
1330  qureg.numQubitsInStateVec = 0;
+
1331  qureg.numAmpsTotal = 0;
+
1332  qureg.numAmpsPerChunk = 0;
+
1333 
+
1334  free(qureg.stateVec.real);
+
1335  free(qureg.stateVec.imag);
+
1336  if (env.numRanks>1){
+
1337  free(qureg.pairStateVec.real);
+
1338  free(qureg.pairStateVec.imag);
+
1339  }
+
1340  qureg.stateVec.real = NULL;
+
1341  qureg.stateVec.imag = NULL;
+
1342  qureg.pairStateVec.real = NULL;
+
1343  qureg.pairStateVec.imag = NULL;
+
1344 }
-

References Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, and Qureg::stateVec.

+

References Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, and Qureg::stateVec.

@@ -5631,46 +5637,46 @@

Returns
probability of qubit measureQubit being zero
-

Definition at line 3474 of file QuEST_cpu.c.

-
3474  {
-
3475  // ----- measured probability
-
3476  qreal totalProbability; // probability (returned) value
-
3477  // ----- temp variables
-
3478  long long int thisTask; // task based approach for expose loop with small granularity
-
3479  long long int numTasks=qureg.numAmpsPerChunk;
-
3480 
-
3481  // ---------------------------------------------------------------- //
-
3482  // find probability //
-
3483  // ---------------------------------------------------------------- //
-
3484 
-
3485  // initialise returned value
-
3486  totalProbability = 0.0;
-
3487 
-
3488  qreal *stateVecReal = qureg.stateVec.real;
-
3489  qreal *stateVecImag = qureg.stateVec.imag;
-
3490 
-
3491 # ifdef _OPENMP
-
3492 # pragma omp parallel \
-
3493  shared (numTasks,stateVecReal,stateVecImag) \
-
3494  private (thisTask) \
-
3495  reduction ( +:totalProbability )
-
3496 # endif
-
3497  {
-
3498 # ifdef _OPENMP
-
3499 # pragma omp for schedule (static)
-
3500 # endif
-
3501  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3502  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
-
3503  + stateVecImag[thisTask]*stateVecImag[thisTask];
-
3504  }
-
3505  }
-
3506 
-
3507  return totalProbability;
-
3508 }
+

Definition at line 3513 of file QuEST_cpu.c.

+
3513  {
+
3514  // ----- measured probability
+
3515  qreal totalProbability; // probability (returned) value
+
3516  // ----- temp variables
+
3517  long long int thisTask; // task based approach for expose loop with small granularity
+
3518  long long int numTasks=qureg.numAmpsPerChunk;
+
3519 
+
3520  // ---------------------------------------------------------------- //
+
3521  // find probability //
+
3522  // ---------------------------------------------------------------- //
+
3523 
+
3524  // initialise returned value
+
3525  totalProbability = 0.0;
+
3526 
+
3527  qreal *stateVecReal = qureg.stateVec.real;
+
3528  qreal *stateVecImag = qureg.stateVec.imag;
+
3529 
+
3530 # ifdef _OPENMP
+
3531 # pragma omp parallel \
+
3532  shared (numTasks,stateVecReal,stateVecImag) \
+
3533  private (thisTask) \
+
3534  reduction ( +:totalProbability )
+
3535 # endif
+
3536  {
+
3537 # ifdef _OPENMP
+
3538 # pragma omp for schedule (static)
+
3539 # endif
+
3540  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3541  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
+
3542  + stateVecImag[thisTask]*stateVecImag[thisTask];
+
3543  }
+
3544  }
+
3545 
+
3546  return totalProbability;
+
3547 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_calcProbOfOutcome().

+

Referenced by statevec_calcProbOfOutcome().

@@ -5712,57 +5718,57 @@

Returns
probability of qubit measureQubit being zero
-

Definition at line 3418 of file QuEST_cpu.c.

-
3420 {
-
3421  // ----- sizes
-
3422  long long int sizeBlock, // size of blocks
-
3423  sizeHalfBlock; // size of blocks halved
-
3424  // ----- indices
-
3425  long long int thisBlock, // current block
-
3426  index; // current index for first half block
-
3427  // ----- measured probability
-
3428  qreal totalProbability; // probability (returned) value
-
3429  // ----- temp variables
-
3430  long long int thisTask;
-
3431  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3432 
-
3433  // ---------------------------------------------------------------- //
-
3434  // dimensions //
-
3435  // ---------------------------------------------------------------- //
-
3436  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3437  // and then the number to skip
-
3438  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3439 
-
3440  // initialise returned value
-
3441  totalProbability = 0.0;
-
3442 
-
3443  qreal *stateVecReal = qureg.stateVec.real;
-
3444  qreal *stateVecImag = qureg.stateVec.imag;
-
3445 
-
3446 # ifdef _OPENMP
-
3447 # pragma omp parallel \
-
3448  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
-
3449  private (thisTask,thisBlock,index) \
-
3450  reduction ( +:totalProbability )
-
3451 # endif
-
3452  {
-
3453 # ifdef _OPENMP
-
3454 # pragma omp for schedule (static)
-
3455 # endif
-
3456  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3457  thisBlock = thisTask / sizeHalfBlock;
-
3458  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3459 
-
3460  totalProbability += stateVecReal[index]*stateVecReal[index]
-
3461  + stateVecImag[index]*stateVecImag[index];
-
3462  }
-
3463  }
-
3464  return totalProbability;
-
3465 }
+

Definition at line 3457 of file QuEST_cpu.c.

+
3459 {
+
3460  // ----- sizes
+
3461  long long int sizeBlock, // size of blocks
+
3462  sizeHalfBlock; // size of blocks halved
+
3463  // ----- indices
+
3464  long long int thisBlock, // current block
+
3465  index; // current index for first half block
+
3466  // ----- measured probability
+
3467  qreal totalProbability; // probability (returned) value
+
3468  // ----- temp variables
+
3469  long long int thisTask;
+
3470  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3471 
+
3472  // ---------------------------------------------------------------- //
+
3473  // dimensions //
+
3474  // ---------------------------------------------------------------- //
+
3475  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
3476  // and then the number to skip
+
3477  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
3478 
+
3479  // initialise returned value
+
3480  totalProbability = 0.0;
+
3481 
+
3482  qreal *stateVecReal = qureg.stateVec.real;
+
3483  qreal *stateVecImag = qureg.stateVec.imag;
+
3484 
+
3485 # ifdef _OPENMP
+
3486 # pragma omp parallel \
+
3487  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
+
3488  private (thisTask,thisBlock,index) \
+
3489  reduction ( +:totalProbability )
+
3490 # endif
+
3491  {
+
3492 # ifdef _OPENMP
+
3493 # pragma omp for schedule (static)
+
3494 # endif
+
3495  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3496  thisBlock = thisTask / sizeHalfBlock;
+
3497  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3498 
+
3499  totalProbability += stateVecReal[index]*stateVecReal[index]
+
3500  + stateVecImag[index]*stateVecImag[index];
+
3501  }
+
3502  }
+
3503  return totalProbability;
+
3504 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_calcProbOfOutcome().

+

Referenced by statevec_calcProbOfOutcome().

@@ -5823,51 +5829,51 @@

Definition at line 3100 of file QuEST_cpu.c.

-
3105 {
-
3106 
-
3107  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
3108  long long int thisTask;
-
3109  long long int numTasks=qureg.numAmpsPerChunk;
-
3110 
-
3111  int sign;
-
3112  if (updateUpper) sign=1;
-
3113  else sign=-1;
-
3114 
-
3115  qreal recRoot2 = 1.0/sqrt(2);
-
3116 
-
3117  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
3118  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
3119  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
3120 
-
3121 # ifdef _OPENMP
-
3122 # pragma omp parallel \
-
3123  default (none) \
-
3124  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
3125  recRoot2, sign, numTasks) \
-
3126  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
3127 # endif
-
3128  {
-
3129 # ifdef _OPENMP
-
3130 # pragma omp for schedule (static)
-
3131 # endif
-
3132  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3133  // store current state vector values in temp variables
-
3134  stateRealUp = stateVecRealUp[thisTask];
-
3135  stateImagUp = stateVecImagUp[thisTask];
-
3136 
-
3137  stateRealLo = stateVecRealLo[thisTask];
-
3138  stateImagLo = stateVecImagLo[thisTask];
-
3139 
-
3140  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
-
3141  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
-
3142  }
-
3143  }
-
3144 }
+

Definition at line 3139 of file QuEST_cpu.c.

+
3144 {
+
3145 
+
3146  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
3147  long long int thisTask;
+
3148  long long int numTasks=qureg.numAmpsPerChunk;
+
3149 
+
3150  int sign;
+
3151  if (updateUpper) sign=1;
+
3152  else sign=-1;
+
3153 
+
3154  qreal recRoot2 = 1.0/sqrt(2);
+
3155 
+
3156  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
3157  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
3158  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
3159 
+
3160 # ifdef _OPENMP
+
3161 # pragma omp parallel \
+
3162  default (none) \
+
3163  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
3164  recRoot2, sign, numTasks) \
+
3165  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
3166 # endif
+
3167  {
+
3168 # ifdef _OPENMP
+
3169 # pragma omp for schedule (static)
+
3170 # endif
+
3171  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3172  // store current state vector values in temp variables
+
3173  stateRealUp = stateVecRealUp[thisTask];
+
3174  stateImagUp = stateVecImagUp[thisTask];
+
3175 
+
3176  stateRealLo = stateVecRealLo[thisTask];
+
3177  stateImagLo = stateVecImagLo[thisTask];
+
3178 
+
3179  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
+
3180  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
+
3181  }
+
3182  }
+
3183 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_hadamard().

+

Referenced by statevec_hadamard().

@@ -5897,59 +5903,59 @@

-

Definition at line 3039 of file QuEST_cpu.c.

-
3040 {
-
3041  long long int sizeBlock, sizeHalfBlock;
-
3042  long long int thisBlock, // current block
-
3043  indexUp,indexLo; // current index and corresponding index in lower half block
-
3044 
-
3045  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
3046  long long int thisTask;
-
3047  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3048 
-
3049  // set dimensions
-
3050  sizeHalfBlock = 1LL << targetQubit;
-
3051  sizeBlock = 2LL * sizeHalfBlock;
-
3052 
-
3053  // Can't use qureg.stateVec as a private OMP var
-
3054  qreal *stateVecReal = qureg.stateVec.real;
-
3055  qreal *stateVecImag = qureg.stateVec.imag;
-
3056 
-
3057  qreal recRoot2 = 1.0/sqrt(2);
-
3058 
-
3059 # ifdef _OPENMP
-
3060 # pragma omp parallel \
-
3061  default (none) \
-
3062  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
-
3063  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
3064 # endif
-
3065  {
-
3066 # ifdef _OPENMP
-
3067 # pragma omp for schedule (static)
-
3068 # endif
-
3069  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3070  thisBlock = thisTask / sizeHalfBlock;
-
3071  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3072  indexLo = indexUp + sizeHalfBlock;
-
3073 
-
3074  stateRealUp = stateVecReal[indexUp];
-
3075  stateImagUp = stateVecImag[indexUp];
-
3076 
-
3077  stateRealLo = stateVecReal[indexLo];
-
3078  stateImagLo = stateVecImag[indexLo];
-
3079 
-
3080  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
3081  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
3082 
-
3083  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
3084  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
3085  }
-
3086  }
-
3087 }
+

Definition at line 3078 of file QuEST_cpu.c.

+
3079 {
+
3080  long long int sizeBlock, sizeHalfBlock;
+
3081  long long int thisBlock, // current block
+
3082  indexUp,indexLo; // current index and corresponding index in lower half block
+
3083 
+
3084  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
3085  long long int thisTask;
+
3086  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3087 
+
3088  // set dimensions
+
3089  sizeHalfBlock = 1LL << targetQubit;
+
3090  sizeBlock = 2LL * sizeHalfBlock;
+
3091 
+
3092  // Can't use qureg.stateVec as a private OMP var
+
3093  qreal *stateVecReal = qureg.stateVec.real;
+
3094  qreal *stateVecImag = qureg.stateVec.imag;
+
3095 
+
3096  qreal recRoot2 = 1.0/sqrt(2);
+
3097 
+
3098 # ifdef _OPENMP
+
3099 # pragma omp parallel \
+
3100  default (none) \
+
3101  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
+
3102  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
3103 # endif
+
3104  {
+
3105 # ifdef _OPENMP
+
3106 # pragma omp for schedule (static)
+
3107 # endif
+
3108  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3109  thisBlock = thisTask / sizeHalfBlock;
+
3110  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3111  indexLo = indexUp + sizeHalfBlock;
+
3112 
+
3113  stateRealUp = stateVecReal[indexUp];
+
3114  stateImagUp = stateVecImag[indexUp];
+
3115 
+
3116  stateRealLo = stateVecReal[indexLo];
+
3117  stateImagLo = stateVecImag[indexLo];
+
3118 
+
3119  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
+
3120  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
+
3121 
+
3122  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
+
3123  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
+
3124  }
+
3125  }
+
3126 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_hadamard().

+

Referenced by statevec_hadamard().

@@ -5969,39 +5975,39 @@

-

Definition at line 1453 of file QuEST_cpu.c.

-
1454 {
-
1455  long long int stateVecSize;
-
1456  long long int index;
-
1457 
-
1458  // dimension of the state vector
-
1459  stateVecSize = qureg.numAmpsPerChunk;
-
1460 
-
1461  // Can't use qureg->stateVec as a private OMP var
-
1462  qreal *stateVecReal = qureg.stateVec.real;
-
1463  qreal *stateVecImag = qureg.stateVec.imag;
-
1464 
-
1465  // initialise the state-vector to all-zeroes
-
1466 # ifdef _OPENMP
-
1467 # pragma omp parallel \
-
1468  default (none) \
-
1469  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1470  private (index)
-
1471 # endif
-
1472  {
-
1473 # ifdef _OPENMP
-
1474 # pragma omp for schedule (static)
-
1475 # endif
-
1476  for (index=0; index<stateVecSize; index++) {
-
1477  stateVecReal[index] = 0.0;
-
1478  stateVecImag[index] = 0.0;
-
1479  }
-
1480  }
-
1481 }
+

Definition at line 1464 of file QuEST_cpu.c.

+
1465 {
+
1466  long long int stateVecSize;
+
1467  long long int index;
+
1468 
+
1469  // dimension of the state vector
+
1470  stateVecSize = qureg.numAmpsPerChunk;
+
1471 
+
1472  // Can't use qureg->stateVec as a private OMP var
+
1473  qreal *stateVecReal = qureg.stateVec.real;
+
1474  qreal *stateVecImag = qureg.stateVec.imag;
+
1475 
+
1476  // initialise the state-vector to all-zeroes
+
1477 # ifdef _OPENMP
+
1478 # pragma omp parallel \
+
1479  default (none) \
+
1480  shared (stateVecSize, stateVecReal, stateVecImag) \
+
1481  private (index)
+
1482 # endif
+
1483  {
+
1484 # ifdef _OPENMP
+
1485 # pragma omp for schedule (static)
+
1486 # endif
+
1487  for (index=0; index<stateVecSize; index++) {
+
1488  stateVecReal[index] = 0.0;
+
1489  stateVecImag[index] = 0.0;
+
1490  }
+
1491  }
+
1492 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_initZeroState().

+

Referenced by statevec_initZeroState().

@@ -6031,41 +6037,41 @@

-

Definition at line 1525 of file QuEST_cpu.c.

-
1526 {
-
1527  long long int stateVecSize;
-
1528  long long int index;
-
1529 
-
1530  // dimension of the state vector
-
1531  stateVecSize = qureg.numAmpsPerChunk;
-
1532 
-
1533  // Can't use qureg->stateVec as a private OMP var
-
1534  qreal *stateVecReal = qureg.stateVec.real;
-
1535  qreal *stateVecImag = qureg.stateVec.imag;
-
1536 
-
1537  // initialise the state to vector to all zeros
-
1538 # ifdef _OPENMP
-
1539 # pragma omp parallel \
-
1540  default (none) \
-
1541  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1542  private (index)
-
1543 # endif
-
1544  {
-
1545 # ifdef _OPENMP
-
1546 # pragma omp for schedule (static)
-
1547 # endif
-
1548  for (index=0; index<stateVecSize; index++) {
-
1549  stateVecReal[index] = 0.0;
-
1550  stateVecImag[index] = 0.0;
-
1551  }
-
1552  }
-
1553 
-
1554  // give the specified classical state prob 1
-
1555  if (qureg.chunkId == stateInd/stateVecSize){
-
1556  stateVecReal[stateInd % stateVecSize] = 1.0;
-
1557  stateVecImag[stateInd % stateVecSize] = 0.0;
-
1558  }
-
1559 }
+

Definition at line 1536 of file QuEST_cpu.c.

+
1537 {
+
1538  long long int stateVecSize;
+
1539  long long int index;
+
1540 
+
1541  // dimension of the state vector
+
1542  stateVecSize = qureg.numAmpsPerChunk;
+
1543 
+
1544  // Can't use qureg->stateVec as a private OMP var
+
1545  qreal *stateVecReal = qureg.stateVec.real;
+
1546  qreal *stateVecImag = qureg.stateVec.imag;
+
1547 
+
1548  // initialise the state to vector to all zeros
+
1549 # ifdef _OPENMP
+
1550 # pragma omp parallel \
+
1551  default (none) \
+
1552  shared (stateVecSize, stateVecReal, stateVecImag) \
+
1553  private (index)
+
1554 # endif
+
1555  {
+
1556 # ifdef _OPENMP
+
1557 # pragma omp for schedule (static)
+
1558 # endif
+
1559  for (index=0; index<stateVecSize; index++) {
+
1560  stateVecReal[index] = 0.0;
+
1561  stateVecImag[index] = 0.0;
+
1562  }
+
1563  }
+
1564 
+
1565  // give the specified classical state prob 1
+
1566  if (qureg.chunkId == stateInd/stateVecSize){
+
1567  stateVecReal[stateInd % stateVecSize] = 1.0;
+
1568  stateVecImag[stateInd % stateVecSize] = 0.0;
+
1569  }
+
1570 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -6095,38 +6101,38 @@

Definition at line 1646 of file QuEST_cpu.c.

-
1647 {
-
1648  long long int chunkSize;
-
1649  long long int index;
-
1650  long long int indexOffset;
-
1651 
-
1652  // dimension of the state vector
-
1653  chunkSize = qureg.numAmpsPerChunk;
-
1654 
-
1655  // Can't use qureg->stateVec as a private OMP var
-
1656  qreal *stateVecReal = qureg.stateVec.real;
-
1657  qreal *stateVecImag = qureg.stateVec.imag;
-
1658 
-
1659  indexOffset = chunkSize * qureg.chunkId;
-
1660 
-
1661  // initialise the state to |0000..0000>
-
1662 # ifdef _OPENMP
-
1663 # pragma omp parallel \
-
1664  default (none) \
-
1665  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
-
1666  private (index)
-
1667 # endif
-
1668  {
-
1669 # ifdef _OPENMP
-
1670 # pragma omp for schedule (static)
-
1671 # endif
-
1672  for (index=0; index<chunkSize; index++) {
-
1673  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
-
1674  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
-
1675  }
-
1676  }
-
1677 }
+

Definition at line 1657 of file QuEST_cpu.c.

+
1658 {
+
1659  long long int chunkSize;
+
1660  long long int index;
+
1661  long long int indexOffset;
+
1662 
+
1663  // dimension of the state vector
+
1664  chunkSize = qureg.numAmpsPerChunk;
+
1665 
+
1666  // Can't use qureg->stateVec as a private OMP var
+
1667  qreal *stateVecReal = qureg.stateVec.real;
+
1668  qreal *stateVecImag = qureg.stateVec.imag;
+
1669 
+
1670  indexOffset = chunkSize * qureg.chunkId;
+
1671 
+
1672  // initialise the state to |0000..0000>
+
1673 # ifdef _OPENMP
+
1674 # pragma omp parallel \
+
1675  default (none) \
+
1676  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
+
1677  private (index)
+
1678 # endif
+
1679  {
+
1680 # ifdef _OPENMP
+
1681 # pragma omp for schedule (static)
+
1682 # endif
+
1683  for (index=0; index<chunkSize; index++) {
+
1684  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
+
1685  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
+
1686  }
+
1687  }
+
1688 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -6148,37 +6154,37 @@

-

Definition at line 1493 of file QuEST_cpu.c.

-
1494 {
-
1495  long long int chunkSize, stateVecSize;
-
1496  long long int index;
-
1497 
-
1498  // dimension of the state vector
-
1499  chunkSize = qureg.numAmpsPerChunk;
-
1500  stateVecSize = chunkSize*qureg.numChunks;
-
1501  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
1502 
-
1503  // Can't use qureg->stateVec as a private OMP var
-
1504  qreal *stateVecReal = qureg.stateVec.real;
-
1505  qreal *stateVecImag = qureg.stateVec.imag;
-
1506 
-
1507  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1508 # ifdef _OPENMP
-
1509 # pragma omp parallel \
-
1510  default (none) \
-
1511  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
-
1512  private (index)
-
1513 # endif
-
1514  {
-
1515 # ifdef _OPENMP
-
1516 # pragma omp for schedule (static)
-
1517 # endif
-
1518  for (index=0; index<chunkSize; index++) {
-
1519  stateVecReal[index] = normFactor;
-
1520  stateVecImag[index] = 0.0;
-
1521  }
-
1522  }
-
1523 }
+

Definition at line 1504 of file QuEST_cpu.c.

+
1505 {
+
1506  long long int chunkSize, stateVecSize;
+
1507  long long int index;
+
1508 
+
1509  // dimension of the state vector
+
1510  chunkSize = qureg.numAmpsPerChunk;
+
1511  stateVecSize = chunkSize*qureg.numChunks;
+
1512  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
+
1513 
+
1514  // Can't use qureg->stateVec as a private OMP var
+
1515  qreal *stateVecReal = qureg.stateVec.real;
+
1516  qreal *stateVecImag = qureg.stateVec.imag;
+
1517 
+
1518  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
+
1519 # ifdef _OPENMP
+
1520 # pragma omp parallel \
+
1521  default (none) \
+
1522  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
+
1523  private (index)
+
1524 # endif
+
1525  {
+
1526 # ifdef _OPENMP
+
1527 # pragma omp for schedule (static)
+
1528 # endif
+
1529  for (index=0; index<chunkSize; index++) {
+
1530  stateVecReal[index] = normFactor;
+
1531  stateVecImag[index] = 0.0;
+
1532  }
+
1533  }
+
1534 }

References Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

@@ -6216,58 +6222,58 @@

-

Definition at line 1680 of file QuEST_cpu.c.

-
1680  {
-
1681  long long int chunkSize, stateVecSize;
-
1682  long long int indexInChunk, totalIndex;
-
1683 
-
1684  chunkSize = qureg->numAmpsPerChunk;
-
1685  stateVecSize = chunkSize*qureg->numChunks;
-
1686 
-
1687  qreal *stateVecReal = qureg->stateVec.real;
-
1688  qreal *stateVecImag = qureg->stateVec.imag;
-
1689 
-
1690  FILE *fp;
-
1691  char line[200];
-
1692 
-
1693  for (int rank=0; rank<(qureg->numChunks); rank++){
-
1694  if (rank==qureg->chunkId){
-
1695  fp = fopen(filename, "r");
-
1696 
-
1697  // indicate file open failure
-
1698  if (fp == NULL)
-
1699  return 0;
-
1700 
-
1701  indexInChunk = 0; totalIndex = 0;
-
1702  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
1703  if (line[0]!='#'){
-
1704  int chunkId = (int) (totalIndex/chunkSize);
-
1705  if (chunkId==qureg->chunkId){
-
1706  # if QuEST_PREC==1
-
1707  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
1708  &(stateVecImag[indexInChunk]));
-
1709  # elif QuEST_PREC==2
-
1710  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
1711  &(stateVecImag[indexInChunk]));
-
1712  # elif QuEST_PREC==4
-
1713  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
-
1714  &(stateVecImag[indexInChunk]));
-
1715  # endif
-
1716  indexInChunk += 1;
-
1717  }
-
1718  totalIndex += 1;
-
1719  }
-
1720  }
-
1721  fclose(fp);
-
1722  }
-
1723  syncQuESTEnv(env);
-
1724  }
-
1725 
-
1726  // indicate success
-
1727  return 1;
-
1728 }
+

Definition at line 1691 of file QuEST_cpu.c.

+
1691  {
+
1692  long long int chunkSize, stateVecSize;
+
1693  long long int indexInChunk, totalIndex;
+
1694 
+
1695  chunkSize = qureg->numAmpsPerChunk;
+
1696  stateVecSize = chunkSize*qureg->numChunks;
+
1697 
+
1698  qreal *stateVecReal = qureg->stateVec.real;
+
1699  qreal *stateVecImag = qureg->stateVec.imag;
+
1700 
+
1701  FILE *fp;
+
1702  char line[200];
+
1703 
+
1704  for (int rank=0; rank<(qureg->numChunks); rank++){
+
1705  if (rank==qureg->chunkId){
+
1706  fp = fopen(filename, "r");
+
1707 
+
1708  // indicate file open failure
+
1709  if (fp == NULL)
+
1710  return 0;
+
1711 
+
1712  indexInChunk = 0; totalIndex = 0;
+
1713  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
+
1714  if (line[0]!='#'){
+
1715  int chunkId = (int) (totalIndex/chunkSize);
+
1716  if (chunkId==qureg->chunkId){
+
1717  # if QuEST_PREC==1
+
1718  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
+
1719  &(stateVecImag[indexInChunk]));
+
1720  # elif QuEST_PREC==2
+
1721  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
1722  &(stateVecImag[indexInChunk]));
+
1723  # elif QuEST_PREC==4
+
1724  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
+
1725  &(stateVecImag[indexInChunk]));
+
1726  # endif
+
1727  indexInChunk += 1;
+
1728  }
+
1729  totalIndex += 1;
+
1730  }
+
1731  }
+
1732  fclose(fp);
+
1733  }
+
1734  syncQuESTEnv(env);
+
1735  }
+
1736 
+
1737  // indicate success
+
1738  return 1;
+
1739 }
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Qureg::stateVec, and syncQuESTEnv().

+

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Qureg::stateVec, and syncQuESTEnv().

@@ -6313,45 +6319,45 @@

Definition at line 1600 of file QuEST_cpu.c.

-
1601 {
-
1602  long long int chunkSize, stateVecSize;
-
1603  long long int index;
-
1604  int bit;
-
1605  long long int chunkId=qureg->chunkId;
-
1606 
-
1607  // dimension of the state vector
-
1608  chunkSize = qureg->numAmpsPerChunk;
-
1609  stateVecSize = chunkSize*qureg->numChunks;
-
1610  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
-
1611 
-
1612  // Can't use qureg->stateVec as a private OMP var
-
1613  qreal *stateVecReal = qureg->stateVec.real;
-
1614  qreal *stateVecImag = qureg->stateVec.imag;
-
1615 
-
1616  // initialise the state to |0000..0000>
-
1617 # ifdef _OPENMP
-
1618 # pragma omp parallel \
-
1619  default (none) \
-
1620  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
-
1621  private (index, bit)
-
1622 # endif
-
1623  {
-
1624 # ifdef _OPENMP
-
1625 # pragma omp for schedule (static)
-
1626 # endif
-
1627  for (index=0; index<chunkSize; index++) {
-
1628  bit = extractBit(qubitId, index+chunkId*chunkSize);
-
1629  if (bit==outcome) {
-
1630  stateVecReal[index] = normFactor;
-
1631  stateVecImag[index] = 0.0;
-
1632  } else {
-
1633  stateVecReal[index] = 0.0;
-
1634  stateVecImag[index] = 0.0;
-
1635  }
-
1636  }
-
1637  }
-
1638 }
+

Definition at line 1611 of file QuEST_cpu.c.

+
1612 {
+
1613  long long int chunkSize, stateVecSize;
+
1614  long long int index;
+
1615  int bit;
+
1616  long long int chunkId=qureg->chunkId;
+
1617 
+
1618  // dimension of the state vector
+
1619  chunkSize = qureg->numAmpsPerChunk;
+
1620  stateVecSize = chunkSize*qureg->numChunks;
+
1621  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
+
1622 
+
1623  // Can't use qureg->stateVec as a private OMP var
+
1624  qreal *stateVecReal = qureg->stateVec.real;
+
1625  qreal *stateVecImag = qureg->stateVec.imag;
+
1626 
+
1627  // initialise the state to |0000..0000>
+
1628 # ifdef _OPENMP
+
1629 # pragma omp parallel \
+
1630  default (none) \
+
1631  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
+
1632  private (index, bit)
+
1633 # endif
+
1634  {
+
1635 # ifdef _OPENMP
+
1636 # pragma omp for schedule (static)
+
1637 # endif
+
1638  for (index=0; index<chunkSize; index++) {
+
1639  bit = extractBit(qubitId, index+chunkId*chunkSize);
+
1640  if (bit==outcome) {
+
1641  stateVecReal[index] = normFactor;
+
1642  stateVecImag[index] = 0.0;
+
1643  } else {
+
1644  stateVecReal[index] = 0.0;
+
1645  stateVecImag[index] = 0.0;
+
1646  }
+
1647  }
+
1648  }
+
1649 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

@@ -6373,17 +6379,17 @@

-

Definition at line 1483 of file QuEST_cpu.c.

-
1484 {
-
1485  statevec_initBlankState(qureg);
-
1486  if (qureg.chunkId==0){
-
1487  // zero state |0000..0000> has probability 1
-
1488  qureg.stateVec.real[0] = 1.0;
-
1489  qureg.stateVec.imag[0] = 0.0;
-
1490  }
-
1491 }
+

Definition at line 1494 of file QuEST_cpu.c.

+
1495 {
+
1496  statevec_initBlankState(qureg);
+
1497  if (qureg.chunkId==0){
+
1498  // zero state |0000..0000> has probability 1
+
1499  qureg.stateVec.real[0] = 1.0;
+
1500  qureg.stateVec.imag[0] = 0.0;
+
1501  }
+
1502 }
-

References Qureg::chunkId, Qureg::stateVec, and statevec_initBlankState().

+

References Qureg::chunkId, Qureg::stateVec, and statevec_initBlankState().

@@ -6431,59 +6437,59 @@

-

Definition at line 2795 of file QuEST_cpu.c.

-
2799  {
-
2800  long long int numAmps = qureg.numAmpsPerChunk;
-
2801  long long int globalOffset = qureg.chunkId * numAmps;
-
2802 
-
2803  /* stateVecOut is qureg's local state-vector partition, which we modify.
-
2804  * stateVecIn is the pair node's state-vector partition, in an order which
-
2805  * does not necessarily correlate to stateVecOut's
-
2806  */
-
2807  qreal* inReal = stateVecIn.real;
-
2808  qreal* inImag = stateVecIn.imag;
-
2809  qreal* outReal = stateVecOut.real;
-
2810  qreal* outImag = stateVecOut.imag;
-
2811 
-
2812  long long int outInd, outIndGlobal, inInd, inIndGlobal;
-
2813 
-
2814 # ifdef _OPENMP
-
2815 # pragma omp parallel \
-
2816  default (none) \
-
2817  shared (inReal,inImag,outReal,outImag, numAmps,globalOffset, ctrlMask,targMask) \
-
2818  private (outInd,outIndGlobal, inInd,inIndGlobal)
-
2819 # endif
-
2820  {
-
2821 # ifdef _OPENMP
-
2822 # pragma omp for schedule (static)
-
2823 # endif
-
2824  for (outInd = 0; outInd < numAmps; outInd++) {
-
2825 
-
2826  // modify amplitude only if control qubits are 1 for this state
-
2827  outIndGlobal = outInd + globalOffset;
-
2828  if (ctrlMask && ((ctrlMask & outIndGlobal) != ctrlMask))
-
2829  continue;
-
2830  /* it is a premature optimisation to remove this seemingly wasteful abort above,
-
2831  * because the maximum skipped amplitudes is 1/2 that stored in the node
-
2832  * (since this function is not called if all amps should be skipped)
-
2833  */
-
2834 
-
2835  /* unlike statevec_controlledNotDistributed(), we cannot assume stateVecOut
-
2836  * maps contiguously/parallel into stateVecIn; we must map each amplitude, bit-wise.
-
2837  * However, the arithmetic doesn't necessitate knowing the rank of stateVecIn
-
2838  */
-
2839  inIndGlobal = outIndGlobal ^ targMask;
-
2840  inInd = inIndGlobal % numAmps; // = inIndGlobal - pairRank * numAmps
-
2841 
-
2842  outReal[outInd] = inReal[inInd];
-
2843  outImag[outInd] = inImag[inInd];
-
2844  }
-
2845  }
-
2846 }
+

Definition at line 2834 of file QuEST_cpu.c.

+
2838  {
+
2839  long long int numAmps = qureg.numAmpsPerChunk;
+
2840  long long int globalOffset = qureg.chunkId * numAmps;
+
2841 
+
2842  /* stateVecOut is qureg's local state-vector partition, which we modify.
+
2843  * stateVecIn is the pair node's state-vector partition, in an order which
+
2844  * does not necessarily correlate to stateVecOut's
+
2845  */
+
2846  qreal* inReal = stateVecIn.real;
+
2847  qreal* inImag = stateVecIn.imag;
+
2848  qreal* outReal = stateVecOut.real;
+
2849  qreal* outImag = stateVecOut.imag;
+
2850 
+
2851  long long int outInd, outIndGlobal, inInd, inIndGlobal;
+
2852 
+
2853 # ifdef _OPENMP
+
2854 # pragma omp parallel \
+
2855  default (none) \
+
2856  shared (inReal,inImag,outReal,outImag, numAmps,globalOffset, ctrlMask,targMask) \
+
2857  private (outInd,outIndGlobal, inInd,inIndGlobal)
+
2858 # endif
+
2859  {
+
2860 # ifdef _OPENMP
+
2861 # pragma omp for schedule (static)
+
2862 # endif
+
2863  for (outInd = 0; outInd < numAmps; outInd++) {
+
2864 
+
2865  // modify amplitude only if control qubits are 1 for this state
+
2866  outIndGlobal = outInd + globalOffset;
+
2867  if (ctrlMask && ((ctrlMask & outIndGlobal) != ctrlMask))
+
2868  continue;
+
2869  /* it is a premature optimisation to remove this seemingly wasteful abort above,
+
2870  * because the maximum skipped amplitudes is 1/2 that stored in the node
+
2871  * (since this function is not called if all amps should be skipped)
+
2872  */
+
2873 
+
2874  /* unlike statevec_controlledNotDistributed(), we cannot assume stateVecOut
+
2875  * maps contiguously/parallel into stateVecIn; we must map each amplitude, bit-wise.
+
2876  * However, the arithmetic doesn't necessitate knowing the rank of stateVecIn
+
2877  */
+
2878  inIndGlobal = outIndGlobal ^ targMask;
+
2879  inInd = inIndGlobal % numAmps; // = inIndGlobal - pairRank * numAmps
+
2880 
+
2881  outReal[outInd] = inReal[inInd];
+
2882  outImag[outInd] = inImag[inInd];
+
2883  }
+
2884  }
+
2885 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_multiControlledMultiQubitNot().

+

Referenced by statevec_multiControlledMultiQubitNot().

@@ -6519,66 +6525,66 @@

-

Definition at line 2739 of file QuEST_cpu.c.

-
2739  {
-
2740  long long int numAmps = qureg.numAmpsPerChunk;
-
2741  qreal* stateRe = qureg.stateVec.real;
-
2742  qreal* stateIm = qureg.stateVec.imag;
-
2743 
-
2744  long long int globalOffset = qureg.chunkId * numAmps;
-
2745 
-
2746  // each amplitude is swapped with a 'mate' amplitude
-
2747  long long int ampInd, mateInd, globalInd;
-
2748  qreal mateRe, mateIm;
-
2749 
-
2750 # ifdef _OPENMP
-
2751 # pragma omp parallel \
-
2752  default (none) \
-
2753  shared (stateRe,stateIm, numAmps, ctrlMask,targMask, globalOffset) \
-
2754  private (ampInd, mateInd,mateRe,mateIm, globalInd)
-
2755 # endif
-
2756  {
-
2757 # ifdef _OPENMP
-
2758 # pragma omp for schedule (static)
-
2759 # endif
-
2760  for (ampInd = 0; ampInd < numAmps; ampInd++) {
-
2761 
-
2762  /* it may be a premature optimisation to remove the seemingly wasteful continues below,
-
2763  * because the maximum skipped amplitudes is 1/2 that stored in the node
-
2764  * (e.g. since this function is not called if all amps should be skipped via controls),
-
2765  * and since we're memory-bandwidth bottlenecked.
-
2766  */
-
2767 
-
2768  // although amps are local, we may still be running in distributed mode,
-
2769  // and hence need to consult the global index to determine the values of
-
2770  // the control qubits
-
2771  globalInd = ampInd + globalOffset;
-
2772 
-
2773  // modify amplitude only if control qubits are 1 for this state
-
2774  if (ctrlMask && ((ctrlMask & globalInd) != ctrlMask))
-
2775  continue;
-
2776 
-
2777  mateInd = ampInd ^ targMask;
-
2778 
-
2779  // if the mate is behind, it was already processed
-
2780  if (mateInd < ampInd)
-
2781  continue;
-
2782 
-
2783  mateRe = stateRe[mateInd];
-
2784  mateIm = stateIm[mateInd];
-
2785 
-
2786  // swap amp with mate
-
2787  stateRe[mateInd] = stateRe[ampInd];
-
2788  stateIm[mateInd] = stateIm[ampInd];
-
2789  stateRe[ampInd] = mateRe;
-
2790  stateIm[ampInd] = mateIm;
-
2791  }
-
2792  }
-
2793 }
+

Definition at line 2778 of file QuEST_cpu.c.

+
2778  {
+
2779  long long int numAmps = qureg.numAmpsPerChunk;
+
2780  qreal* stateRe = qureg.stateVec.real;
+
2781  qreal* stateIm = qureg.stateVec.imag;
+
2782 
+
2783  long long int globalOffset = qureg.chunkId * numAmps;
+
2784 
+
2785  // each amplitude is swapped with a 'mate' amplitude
+
2786  long long int ampInd, mateInd, globalInd;
+
2787  qreal mateRe, mateIm;
+
2788 
+
2789 # ifdef _OPENMP
+
2790 # pragma omp parallel \
+
2791  default (none) \
+
2792  shared (stateRe,stateIm, numAmps, ctrlMask,targMask, globalOffset) \
+
2793  private (ampInd, mateInd,mateRe,mateIm, globalInd)
+
2794 # endif
+
2795  {
+
2796 # ifdef _OPENMP
+
2797 # pragma omp for schedule (static)
+
2798 # endif
+
2799  for (ampInd = 0; ampInd < numAmps; ampInd++) {
+
2800 
+
2801  /* it may be a premature optimisation to remove the seemingly wasteful continues below,
+
2802  * because the maximum skipped amplitudes is 1/2 that stored in the node
+
2803  * (e.g. since this function is not called if all amps should be skipped via controls),
+
2804  * and since we're memory-bandwidth bottlenecked.
+
2805  */
+
2806 
+
2807  // although amps are local, we may still be running in distributed mode,
+
2808  // and hence need to consult the global index to determine the values of
+
2809  // the control qubits
+
2810  globalInd = ampInd + globalOffset;
+
2811 
+
2812  // modify amplitude only if control qubits are 1 for this state
+
2813  if (ctrlMask && ((ctrlMask & globalInd) != ctrlMask))
+
2814  continue;
+
2815 
+
2816  mateInd = ampInd ^ targMask;
+
2817 
+
2818  // if the mate is behind, it was already processed
+
2819  if (mateInd < ampInd)
+
2820  continue;
+
2821 
+
2822  mateRe = stateRe[mateInd];
+
2823  mateIm = stateIm[mateInd];
+
2824 
+
2825  // swap amp with mate
+
2826  stateRe[mateInd] = stateRe[ampInd];
+
2827  stateIm[mateInd] = stateIm[ampInd];
+
2828  stateRe[ampInd] = mateRe;
+
2829  stateIm[ampInd] = mateIm;
+
2830  }
+
2831  }
+
2832 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_multiControlledMultiQubitNot().

+

Referenced by statevec_multiControlledMultiQubitNot().

@@ -6626,95 +6632,123 @@

-

Definition at line 1901 of file QuEST_cpu.c.

-
1902 {
-
1903  // can't use qureg.stateVec as a private OMP var
-
1904  qreal *reVec = qureg.stateVec.real;
-
1905  qreal *imVec = qureg.stateVec.imag;
-
1906 
-
1907  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
1908  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
-
1909 
-
1910  // the global (between all nodes) index of this node's start index
-
1911  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1912 
-
1913  long long int thisTask;
-
1914  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
-
1915  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
-
1916  long long int ind; // each thread's iteration of amplitudes to modify
-
1917  int i, t, r, c; // each thread's iteration of amps and targets
-
1918  qreal reElem, imElem; // each thread's iteration of u elements
-
1919 
-
1920  // each thread/task will record and modify numTargAmps amplitudes, privately
-
1921  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
-
1922  long long int ampInds[numTargAmps];
-
1923  qreal reAmps[numTargAmps];
-
1924  qreal imAmps[numTargAmps];
-
1925 
-
1926  // we need a sorted targets list to find thisInd00 for each task.
-
1927  // we can't modify targets, because the user-ordering of targets matters in u
-
1928  int sortedTargs[numTargs];
-
1929  for (int t=0; t < numTargs; t++)
-
1930  sortedTargs[t] = targs[t];
-
1931  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
-
1932 
-
1933 # ifdef _OPENMP
-
1934 # pragma omp parallel \
-
1935  default (none) \
-
1936  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
-
1937  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
-
1938 # endif
-
1939  {
-
1940 # ifdef _OPENMP
-
1941 # pragma omp for schedule (static)
-
1942 # endif
-
1943  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1944 
-
1945  // find this task's start index (where all targs are 0)
-
1946  thisInd00 = thisTask;
-
1947  for (t=0; t < numTargs; t++)
-
1948  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
-
1949 
-
1950  // this task only modifies amplitudes if control qubits are 1 for this state
-
1951  thisGlobalInd00 = thisInd00 + globalIndStart;
-
1952  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1953  continue;
-
1954 
-
1955  // determine the indices and record values of this tasks's target amps
-
1956  for (i=0; i < numTargAmps; i++) {
-
1957 
-
1958  // get statevec index of current target qubit assignment
-
1959  ind = thisInd00;
-
1960  for (t=0; t < numTargs; t++)
-
1961  if (extractBit(t, i))
-
1962  ind = flipBit(ind, targs[t]);
-
1963 
-
1964  // update this tasks's private arrays
-
1965  ampInds[i] = ind;
-
1966  reAmps [i] = reVec[ind];
-
1967  imAmps [i] = imVec[ind];
-
1968  }
-
1969 
-
1970  // modify this tasks's target amplitudes
-
1971  for (r=0; r < numTargAmps; r++) {
-
1972  ind = ampInds[r];
-
1973  reVec[ind] = 0;
-
1974  imVec[ind] = 0;
-
1975 
-
1976  for (c=0; c < numTargAmps; c++) {
-
1977  reElem = u.real[r][c];
-
1978  imElem = u.imag[r][c];
-
1979  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
-
1980  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
-
1981  }
-
1982  }
-
1983  }
-
1984  }
-
1985 }
+

Definition at line 1912 of file QuEST_cpu.c.

+
1913 {
+
1914  // can't use qureg.stateVec as a private OMP var
+
1915  qreal *reVec = qureg.stateVec.real;
+
1916  qreal *imVec = qureg.stateVec.imag;
+
1917 
+
1918  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
+
1919  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
+
1920 
+
1921  // the global (between all nodes) index of this node's start index
+
1922  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
+
1923 
+
1924  long long int thisTask;
+
1925  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
+
1926  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
+
1927  long long int ind; // each thread's iteration of amplitudes to modify
+
1928  int i, t, r, c; // each thread's iteration of amps and targets
+
1929  qreal reElem, imElem; // each thread's iteration of u elements
+
1930 
+
1931  // each thread/task will record and modify numTargAmps amplitudes, privately
+
1932  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
+
1933  //
+
1934  // If we're NOT on windows, we can fortunately use the stack directly
+
1935  #ifndef _WIN32
+
1936  long long int ampInds[numTargAmps];
+
1937  qreal reAmps[numTargAmps];
+
1938  qreal imAmps[numTargAmps];
+
1939 
+
1940  int sortedTargs[numTargs];
+
1941  // on Windows, with no VLA, we can use _malloca to allocate on stack (must free)
+
1942  #else
+
1943  long long int* ampInds;
+
1944  qreal* reAmps;
+
1945  qreal* imAmps;
+
1946  int* sortedTargs = (int*) _malloca(numTargs * sizeof *sortedTargs);
+
1947  #endif
+
1948 
+
1949  // we need a sorted targets list to find thisInd00 for each task.
+
1950  // we can't modify targets, because the user-ordering of targets matters in u
+
1951  for (int t=0; t < numTargs; t++)
+
1952  sortedTargs[t] = targs[t];
+
1953  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
+
1954 
+
1955 # ifdef _OPENMP
+
1956 # pragma omp parallel \
+
1957  default (none) \
+
1958  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
+
1959  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
+
1960 # endif
+
1961  {
+
1962  // when manually allocating array memory (on Windows), this must be done in each thread
+
1963  // separately and is not performed automatically by declaring a var as omp-private
+
1964  # ifdef _WIN32
+
1965  ampInds = (long long int*) _malloca(numTargAmps * sizeof *ampInds);
+
1966  reAmps = (qreal*) _malloca(numTargAmps * sizeof *reAmps);
+
1967  imAmps = (qreal*) _malloca(numTargAmps * sizeof *imAmps);
+
1968  # endif
+
1969 # ifdef _OPENMP
+
1970 # pragma omp for schedule (static)
+
1971 # endif
+
1972  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
1973 
+
1974  // find this task's start index (where all targs are 0)
+
1975  thisInd00 = thisTask;
+
1976  for (t=0; t < numTargs; t++)
+
1977  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
+
1978 
+
1979  // this task only modifies amplitudes if control qubits are 1 for this state
+
1980  thisGlobalInd00 = thisInd00 + globalIndStart;
+
1981  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
+
1982  continue;
+
1983 
+
1984  // determine the indices and record values of this tasks's target amps
+
1985  for (i=0; i < numTargAmps; i++) {
+
1986 
+
1987  // get statevec index of current target qubit assignment
+
1988  ind = thisInd00;
+
1989  for (t=0; t < numTargs; t++)
+
1990  if (extractBit(t, i))
+
1991  ind = flipBit(ind, targs[t]);
+
1992 
+
1993  // update this tasks's private arrays
+
1994  ampInds[i] = ind;
+
1995  reAmps [i] = reVec[ind];
+
1996  imAmps [i] = imVec[ind];
+
1997  }
+
1998 
+
1999  // modify this tasks's target amplitudes
+
2000  for (r=0; r < numTargAmps; r++) {
+
2001  ind = ampInds[r];
+
2002  reVec[ind] = 0;
+
2003  imVec[ind] = 0;
+
2004 
+
2005  for (c=0; c < numTargAmps; c++) {
+
2006  reElem = u.real[r][c];
+
2007  imElem = u.imag[r][c];
+
2008  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
+
2009  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
+
2010  }
+
2011  }
+
2012  }
+
2013  // on Windows, we must explicitly free the stack structures
+
2014  #ifdef _WIN32
+
2015  _freea(ampInds);
+
2016  _freea(reAmps);
+
2017  _freea(imAmps);
+
2018  #endif
+
2019  }
+
2020 
+
2021  #ifdef _WIN32
+
2022  _freea(sortedTargs);
+
2023  #endif
+
2024 }
-

References Qureg::chunkId, extractBit(), flipBit(), ComplexMatrixN::imag, insertZeroBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, qsortComp(), ComplexMatrixN::real, and Qureg::stateVec.

+

References Qureg::chunkId, extractBit(), flipBit(), ComplexMatrixN::imag, insertZeroBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, qsortComp(), ComplexMatrixN::real, and Qureg::stateVec.

-

Referenced by statevec_multiControlledMultiQubitUnitary().

+

Referenced by statevec_multiControlledMultiQubitUnitary().

@@ -6756,51 +6790,51 @@

-

Definition at line 3319 of file QuEST_cpu.c.

-
3320 {
-
3321  long long int offset = qureg.chunkId * qureg.numAmpsPerChunk;
-
3322 
-
3323  long long int stateVecSize = qureg.numAmpsPerChunk;
-
3324  qreal *stateVecReal = qureg.stateVec.real;
-
3325  qreal *stateVecImag = qureg.stateVec.imag;
-
3326 
-
3327  qreal stateReal, stateImag;
-
3328  qreal cosAngle = cos(angle/2.0);
-
3329  qreal sinAngle = sin(angle/2.0);
-
3330 
-
3331  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3332  // exp(-angle/2 i fac_j)|j>
-
3333  int fac;
-
3334  long long int index, globalIndex;
-
3335 
-
3336 # ifdef _OPENMP
-
3337 # pragma omp parallel \
-
3338  default (none) \
-
3339  shared (offset, stateVecSize, stateVecReal,stateVecImag, ctrlMask,targMask, cosAngle,sinAngle) \
-
3340  private (index,globalIndex, fac, stateReal,stateImag)
-
3341 # endif
-
3342  {
-
3343 # ifdef _OPENMP
-
3344 # pragma omp for schedule (static)
-
3345 # endif
-
3346  for (index=0; index<stateVecSize; index++) {
-
3347  stateReal = stateVecReal[index];
-
3348  stateImag = stateVecImag[index];
-
3349 
-
3350  // states with not-all-one control qubits are unmodified
-
3351  globalIndex = index + offset;
-
3352  if (ctrlMask && ((ctrlMask & globalIndex) != ctrlMask))
-
3353  continue;
-
3354 
-
3355  // odd-parity target qubits get fac_j = -1 (avoid thread divergence)
-
3356  fac = 1-2*getBitMaskParity(targMask & globalIndex);
-
3357  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3358  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3359  }
-
3360  }
-
3361 }
+

Definition at line 3358 of file QuEST_cpu.c.

+
3359 {
+
3360  long long int offset = qureg.chunkId * qureg.numAmpsPerChunk;
+
3361 
+
3362  long long int stateVecSize = qureg.numAmpsPerChunk;
+
3363  qreal *stateVecReal = qureg.stateVec.real;
+
3364  qreal *stateVecImag = qureg.stateVec.imag;
+
3365 
+
3366  qreal stateReal, stateImag;
+
3367  qreal cosAngle = cos(angle/2.0);
+
3368  qreal sinAngle = sin(angle/2.0);
+
3369 
+
3370  // = +-1, to flip sinAngle based on target qubit parity, to effect
+
3371  // exp(-angle/2 i fac_j)|j>
+
3372  int fac;
+
3373  long long int index, globalIndex;
+
3374 
+
3375 # ifdef _OPENMP
+
3376 # pragma omp parallel \
+
3377  default (none) \
+
3378  shared (offset, stateVecSize, stateVecReal,stateVecImag, ctrlMask,targMask, cosAngle,sinAngle) \
+
3379  private (index,globalIndex, fac, stateReal,stateImag)
+
3380 # endif
+
3381  {
+
3382 # ifdef _OPENMP
+
3383 # pragma omp for schedule (static)
+
3384 # endif
+
3385  for (index=0; index<stateVecSize; index++) {
+
3386  stateReal = stateVecReal[index];
+
3387  stateImag = stateVecImag[index];
+
3388 
+
3389  // states with not-all-one control qubits are unmodified
+
3390  globalIndex = index + offset;
+
3391  if (ctrlMask && ((ctrlMask & globalIndex) != ctrlMask))
+
3392  continue;
+
3393 
+
3394  // odd-parity target qubits get fac_j = -1 (avoid thread divergence)
+
3395  fac = 1-2*getBitMaskParity(targMask & globalIndex);
+
3396  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
3397  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
3398  }
+
3399  }
+
3400 }
-

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -6836,38 +6870,38 @@

-

Definition at line 3678 of file QuEST_cpu.c.

-
3679 {
-
3680  long long int index;
-
3681  long long int stateVecSize;
-
3682 
-
3683  long long int chunkSize=qureg.numAmpsPerChunk;
-
3684  long long int chunkId=qureg.chunkId;
-
3685 
-
3686  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3687 
-
3688  stateVecSize = qureg.numAmpsPerChunk;
-
3689  qreal *stateVecReal = qureg.stateVec.real;
-
3690  qreal *stateVecImag = qureg.stateVec.imag;
-
3691 
-
3692 # ifdef _OPENMP
-
3693 # pragma omp parallel \
-
3694  default (none) \
-
3695  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
-
3696  private (index)
-
3697 # endif
-
3698  {
-
3699 # ifdef _OPENMP
-
3700 # pragma omp for schedule (static)
-
3701 # endif
-
3702  for (index=0; index<stateVecSize; index++) {
-
3703  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3704  stateVecReal [index] = - stateVecReal [index];
-
3705  stateVecImag [index] = - stateVecImag [index];
-
3706  }
-
3707  }
-
3708  }
-
3709 }
+

Definition at line 3718 of file QuEST_cpu.c.

+
3719 {
+
3720  long long int index;
+
3721  long long int stateVecSize;
+
3722 
+
3723  long long int chunkSize=qureg.numAmpsPerChunk;
+
3724  long long int chunkId=qureg.chunkId;
+
3725 
+
3726  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
3727 
+
3728  stateVecSize = qureg.numAmpsPerChunk;
+
3729  qreal *stateVecReal = qureg.stateVec.real;
+
3730  qreal *stateVecImag = qureg.stateVec.imag;
+
3731 
+
3732 # ifdef _OPENMP
+
3733 # pragma omp parallel \
+
3734  default (none) \
+
3735  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
+
3736  private (index)
+
3737 # endif
+
3738  {
+
3739 # ifdef _OPENMP
+
3740 # pragma omp for schedule (static)
+
3741 # endif
+
3742  for (index=0; index<stateVecSize; index++) {
+
3743  if (mask == (mask & (index+chunkId*chunkSize)) ){
+
3744  stateVecReal [index] = - stateVecReal [index];
+
3745  stateVecImag [index] = - stateVecImag [index];
+
3746  }
+
3747  }
+
3748  }
+
3749 }

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -6911,46 +6945,46 @@

-

Definition at line 3227 of file QuEST_cpu.c.

-
3228 {
-
3229  long long int index;
-
3230  long long int stateVecSize;
-
3231 
-
3232  long long int chunkSize=qureg.numAmpsPerChunk;
-
3233  long long int chunkId=qureg.chunkId;
-
3234 
-
3235  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3236 
-
3237  stateVecSize = qureg.numAmpsPerChunk;
-
3238  qreal *stateVecReal = qureg.stateVec.real;
-
3239  qreal *stateVecImag = qureg.stateVec.imag;
-
3240 
-
3241  qreal stateRealLo, stateImagLo;
-
3242  qreal cosAngle = cos(angle);
-
3243  qreal sinAngle = sin(angle);
-
3244 
-
3245 # ifdef _OPENMP
-
3246 # pragma omp parallel \
-
3247  default (none) \
-
3248  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3249  private (index, stateRealLo, stateImagLo)
-
3250 # endif
-
3251  {
-
3252 # ifdef _OPENMP
-
3253 # pragma omp for schedule (static)
-
3254 # endif
-
3255  for (index=0; index<stateVecSize; index++) {
-
3256  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3257 
-
3258  stateRealLo = stateVecReal[index];
-
3259  stateImagLo = stateVecImag[index];
-
3260 
-
3261  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3262  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3263  }
-
3264  }
-
3265  }
-
3266 }
+

Definition at line 3266 of file QuEST_cpu.c.

+
3267 {
+
3268  long long int index;
+
3269  long long int stateVecSize;
+
3270 
+
3271  long long int chunkSize=qureg.numAmpsPerChunk;
+
3272  long long int chunkId=qureg.chunkId;
+
3273 
+
3274  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
3275 
+
3276  stateVecSize = qureg.numAmpsPerChunk;
+
3277  qreal *stateVecReal = qureg.stateVec.real;
+
3278  qreal *stateVecImag = qureg.stateVec.imag;
+
3279 
+
3280  qreal stateRealLo, stateImagLo;
+
3281  qreal cosAngle = cos(angle);
+
3282  qreal sinAngle = sin(angle);
+
3283 
+
3284 # ifdef _OPENMP
+
3285 # pragma omp parallel \
+
3286  default (none) \
+
3287  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
+
3288  private (index, stateRealLo, stateImagLo)
+
3289 # endif
+
3290  {
+
3291 # ifdef _OPENMP
+
3292 # pragma omp for schedule (static)
+
3293 # endif
+
3294  for (index=0; index<stateVecSize; index++) {
+
3295  if (mask == (mask & (index+chunkId*chunkSize)) ){
+
3296 
+
3297  stateRealLo = stateVecReal[index];
+
3298  stateImagLo = stateVecImag[index];
+
3299 
+
3300  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3301  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3302  }
+
3303  }
+
3304  }
+
3305 }

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -7000,105 +7034,105 @@

-

Definition at line 1802 of file QuEST_cpu.c.

-
1802  {
-
1803 
-
1804  // can't use qureg.stateVec as a private OMP var
-
1805  qreal *reVec = qureg.stateVec.real;
-
1806  qreal *imVec = qureg.stateVec.imag;
-
1807 
-
1808  // the global (between all nodes) index of this node's start index
-
1809  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1810 
-
1811  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
-
1812  long long int thisTask;
-
1813  long long int thisGlobalInd00;
-
1814  long long int ind00, ind01, ind10, ind11;
-
1815  qreal re00, re01, re10, re11;
-
1816  qreal im00, im01, im10, im11;
-
1817 
-
1818 # ifdef _OPENMP
-
1819 # pragma omp parallel \
-
1820  default (none) \
-
1821  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
-
1822  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
-
1823 # endif
-
1824  {
-
1825 # ifdef _OPENMP
-
1826 # pragma omp for schedule (static)
-
1827 # endif
-
1828  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1829 
-
1830  // determine ind00 of |..0..0..>
-
1831  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1832 
-
1833  // skip amplitude if controls aren't in 1 state (overloaded for speed)
-
1834  thisGlobalInd00 = ind00 + globalIndStart;
-
1835  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1836  continue;
-
1837 
-
1838  // inds of |..0..1..>, |..1..0..> and |..1..1..>
-
1839  ind01 = flipBit(ind00, q1);
-
1840  ind10 = flipBit(ind00, q2);
-
1841  ind11 = flipBit(ind01, q2);
-
1842 
-
1843  // extract statevec amplitudes
-
1844  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1845  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1846  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1847  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1848 
-
1849  // apply u * {amp00, amp01, amp10, amp11}
-
1850  reVec[ind00] =
-
1851  u.real[0][0]*re00 - u.imag[0][0]*im00 +
-
1852  u.real[0][1]*re01 - u.imag[0][1]*im01 +
-
1853  u.real[0][2]*re10 - u.imag[0][2]*im10 +
-
1854  u.real[0][3]*re11 - u.imag[0][3]*im11;
-
1855  imVec[ind00] =
-
1856  u.imag[0][0]*re00 + u.real[0][0]*im00 +
-
1857  u.imag[0][1]*re01 + u.real[0][1]*im01 +
-
1858  u.imag[0][2]*re10 + u.real[0][2]*im10 +
-
1859  u.imag[0][3]*re11 + u.real[0][3]*im11;
-
1860 
-
1861  reVec[ind01] =
-
1862  u.real[1][0]*re00 - u.imag[1][0]*im00 +
-
1863  u.real[1][1]*re01 - u.imag[1][1]*im01 +
-
1864  u.real[1][2]*re10 - u.imag[1][2]*im10 +
-
1865  u.real[1][3]*re11 - u.imag[1][3]*im11;
-
1866  imVec[ind01] =
-
1867  u.imag[1][0]*re00 + u.real[1][0]*im00 +
-
1868  u.imag[1][1]*re01 + u.real[1][1]*im01 +
-
1869  u.imag[1][2]*re10 + u.real[1][2]*im10 +
-
1870  u.imag[1][3]*re11 + u.real[1][3]*im11;
+

Definition at line 1813 of file QuEST_cpu.c.

+
1813  {
+
1814 
+
1815  // can't use qureg.stateVec as a private OMP var
+
1816  qreal *reVec = qureg.stateVec.real;
+
1817  qreal *imVec = qureg.stateVec.imag;
+
1818 
+
1819  // the global (between all nodes) index of this node's start index
+
1820  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
+
1821 
+
1822  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
+
1823  long long int thisTask;
+
1824  long long int thisGlobalInd00;
+
1825  long long int ind00, ind01, ind10, ind11;
+
1826  qreal re00, re01, re10, re11;
+
1827  qreal im00, im01, im10, im11;
+
1828 
+
1829 # ifdef _OPENMP
+
1830 # pragma omp parallel \
+
1831  default (none) \
+
1832  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
+
1833  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
+
1834 # endif
+
1835  {
+
1836 # ifdef _OPENMP
+
1837 # pragma omp for schedule (static)
+
1838 # endif
+
1839  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
1840 
+
1841  // determine ind00 of |..0..0..>
+
1842  ind00 = insertTwoZeroBits(thisTask, q1, q2);
+
1843 
+
1844  // skip amplitude if controls aren't in 1 state (overloaded for speed)
+
1845  thisGlobalInd00 = ind00 + globalIndStart;
+
1846  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
+
1847  continue;
+
1848 
+
1849  // inds of |..0..1..>, |..1..0..> and |..1..1..>
+
1850  ind01 = flipBit(ind00, q1);
+
1851  ind10 = flipBit(ind00, q2);
+
1852  ind11 = flipBit(ind01, q2);
+
1853 
+
1854  // extract statevec amplitudes
+
1855  re00 = reVec[ind00]; im00 = imVec[ind00];
+
1856  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1857  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1858  re11 = reVec[ind11]; im11 = imVec[ind11];
+
1859 
+
1860  // apply u * {amp00, amp01, amp10, amp11}
+
1861  reVec[ind00] =
+
1862  u.real[0][0]*re00 - u.imag[0][0]*im00 +
+
1863  u.real[0][1]*re01 - u.imag[0][1]*im01 +
+
1864  u.real[0][2]*re10 - u.imag[0][2]*im10 +
+
1865  u.real[0][3]*re11 - u.imag[0][3]*im11;
+
1866  imVec[ind00] =
+
1867  u.imag[0][0]*re00 + u.real[0][0]*im00 +
+
1868  u.imag[0][1]*re01 + u.real[0][1]*im01 +
+
1869  u.imag[0][2]*re10 + u.real[0][2]*im10 +
+
1870  u.imag[0][3]*re11 + u.real[0][3]*im11;
1871 
-
1872  reVec[ind10] =
-
1873  u.real[2][0]*re00 - u.imag[2][0]*im00 +
-
1874  u.real[2][1]*re01 - u.imag[2][1]*im01 +
-
1875  u.real[2][2]*re10 - u.imag[2][2]*im10 +
-
1876  u.real[2][3]*re11 - u.imag[2][3]*im11;
-
1877  imVec[ind10] =
-
1878  u.imag[2][0]*re00 + u.real[2][0]*im00 +
-
1879  u.imag[2][1]*re01 + u.real[2][1]*im01 +
-
1880  u.imag[2][2]*re10 + u.real[2][2]*im10 +
-
1881  u.imag[2][3]*re11 + u.real[2][3]*im11;
+
1872  reVec[ind01] =
+
1873  u.real[1][0]*re00 - u.imag[1][0]*im00 +
+
1874  u.real[1][1]*re01 - u.imag[1][1]*im01 +
+
1875  u.real[1][2]*re10 - u.imag[1][2]*im10 +
+
1876  u.real[1][3]*re11 - u.imag[1][3]*im11;
+
1877  imVec[ind01] =
+
1878  u.imag[1][0]*re00 + u.real[1][0]*im00 +
+
1879  u.imag[1][1]*re01 + u.real[1][1]*im01 +
+
1880  u.imag[1][2]*re10 + u.real[1][2]*im10 +
+
1881  u.imag[1][3]*re11 + u.real[1][3]*im11;
1882 
-
1883  reVec[ind11] =
-
1884  u.real[3][0]*re00 - u.imag[3][0]*im00 +
-
1885  u.real[3][1]*re01 - u.imag[3][1]*im01 +
-
1886  u.real[3][2]*re10 - u.imag[3][2]*im10 +
-
1887  u.real[3][3]*re11 - u.imag[3][3]*im11;
-
1888  imVec[ind11] =
-
1889  u.imag[3][0]*re00 + u.real[3][0]*im00 +
-
1890  u.imag[3][1]*re01 + u.real[3][1]*im01 +
-
1891  u.imag[3][2]*re10 + u.real[3][2]*im10 +
-
1892  u.imag[3][3]*re11 + u.real[3][3]*im11;
-
1893  }
-
1894  }
-
1895 }
+
1883  reVec[ind10] =
+
1884  u.real[2][0]*re00 - u.imag[2][0]*im00 +
+
1885  u.real[2][1]*re01 - u.imag[2][1]*im01 +
+
1886  u.real[2][2]*re10 - u.imag[2][2]*im10 +
+
1887  u.real[2][3]*re11 - u.imag[2][3]*im11;
+
1888  imVec[ind10] =
+
1889  u.imag[2][0]*re00 + u.real[2][0]*im00 +
+
1890  u.imag[2][1]*re01 + u.real[2][1]*im01 +
+
1891  u.imag[2][2]*re10 + u.real[2][2]*im10 +
+
1892  u.imag[2][3]*re11 + u.real[2][3]*im11;
+
1893 
+
1894  reVec[ind11] =
+
1895  u.real[3][0]*re00 - u.imag[3][0]*im00 +
+
1896  u.real[3][1]*re01 - u.imag[3][1]*im01 +
+
1897  u.real[3][2]*re10 - u.imag[3][2]*im10 +
+
1898  u.real[3][3]*re11 - u.imag[3][3]*im11;
+
1899  imVec[ind11] =
+
1900  u.imag[3][0]*re00 + u.real[3][0]*im00 +
+
1901  u.imag[3][1]*re01 + u.real[3][1]*im01 +
+
1902  u.imag[3][2]*re10 + u.real[3][2]*im10 +
+
1903  u.imag[3][3]*re11 + u.real[3][3]*im11;
+
1904  }
+
1905  }
+
1906 }

References Qureg::chunkId, flipBit(), ComplexMatrix4::imag, insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, ComplexMatrix4::real, and Qureg::stateVec.

-

Referenced by statevec_multiControlledTwoQubitUnitary().

+

Referenced by statevec_multiControlledTwoQubitUnitary().

@@ -7187,53 +7221,53 @@

Definition at line 2503 of file QuEST_cpu.c.

-
2511 {
-
2512 
-
2513  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2514  long long int thisTask;
-
2515  long long int numTasks=qureg.numAmpsPerChunk;
-
2516  long long int chunkSize=qureg.numAmpsPerChunk;
-
2517  long long int chunkId=qureg.chunkId;
-
2518 
-
2519  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2520  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2521  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2522  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2523  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2524 
-
2525 # ifdef _OPENMP
-
2526 # pragma omp parallel \
-
2527  default (none) \
-
2528  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2529  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
-
2530  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2531 # endif
-
2532  {
-
2533 # ifdef _OPENMP
-
2534 # pragma omp for schedule (static)
-
2535 # endif
-
2536  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2537  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2538  // store current state vector values in temp variables
-
2539  stateRealUp = stateVecRealUp[thisTask];
-
2540  stateImagUp = stateVecImagUp[thisTask];
-
2541 
-
2542  stateRealLo = stateVecRealLo[thisTask];
-
2543  stateImagLo = stateVecImagLo[thisTask];
-
2544 
-
2545  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2546  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2547  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2548  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2549  }
-
2550  }
-
2551  }
-
2552 }
+

Definition at line 2542 of file QuEST_cpu.c.

+
2550 {
+
2551 
+
2552  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2553  long long int thisTask;
+
2554  long long int numTasks=qureg.numAmpsPerChunk;
+
2555  long long int chunkSize=qureg.numAmpsPerChunk;
+
2556  long long int chunkId=qureg.chunkId;
+
2557 
+
2558  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2559  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2560  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2561  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2562  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2563 
+
2564 # ifdef _OPENMP
+
2565 # pragma omp parallel \
+
2566  default (none) \
+
2567  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2568  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
+
2569  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2570 # endif
+
2571  {
+
2572 # ifdef _OPENMP
+
2573 # pragma omp for schedule (static)
+
2574 # endif
+
2575  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2576  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
+
2577  // store current state vector values in temp variables
+
2578  stateRealUp = stateVecRealUp[thisTask];
+
2579  stateImagUp = stateVecImagUp[thisTask];
+
2580 
+
2581  stateRealLo = stateVecRealLo[thisTask];
+
2582  stateImagLo = stateVecImagLo[thisTask];
+
2583 
+
2584  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2585  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2586  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2587  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2588  }
+
2589  }
+
2590  }
+
2591 }

References Qureg::chunkId, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_multiControlledUnitary().

+

Referenced by statevec_multiControlledUnitary().

@@ -7281,74 +7315,74 @@

-

Definition at line 2229 of file QuEST_cpu.c.

-
2233 {
-
2234  long long int sizeBlock, sizeHalfBlock;
-
2235  long long int thisBlock, // current block
-
2236  indexUp,indexLo; // current index and corresponding index in lower half block
-
2237 
-
2238  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2239  long long int thisTask;
-
2240  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2241  long long int chunkSize=qureg.numAmpsPerChunk;
-
2242  long long int chunkId=qureg.chunkId;
-
2243 
-
2244  // set dimensions
-
2245  sizeHalfBlock = 1LL << targetQubit;
-
2246  sizeBlock = 2LL * sizeHalfBlock;
-
2247 
-
2248  // Can't use qureg.stateVec as a private OMP var
-
2249  qreal *stateVecReal = qureg.stateVec.real;
-
2250  qreal *stateVecImag = qureg.stateVec.imag;
-
2251 
-
2252 # ifdef _OPENMP
-
2253 # pragma omp parallel \
-
2254  default (none) \
-
2255  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
-
2256  numTasks,chunkId,chunkSize) \
-
2257  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2258 # endif
-
2259  {
-
2260 # ifdef _OPENMP
-
2261 # pragma omp for schedule (static)
-
2262 # endif
-
2263  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2264 
-
2265  thisBlock = thisTask / sizeHalfBlock;
-
2266  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2267  indexLo = indexUp + sizeHalfBlock;
-
2268 
-
2269 
-
2270  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
-
2271  // if this equals the control mask, the control qubits have the desired values in the basis index
-
2272  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2273  // store current state vector values in temp variables
-
2274  stateRealUp = stateVecReal[indexUp];
-
2275  stateImagUp = stateVecImag[indexUp];
+

Definition at line 2268 of file QuEST_cpu.c.

+
2272 {
+
2273  long long int sizeBlock, sizeHalfBlock;
+
2274  long long int thisBlock, // current block
+
2275  indexUp,indexLo; // current index and corresponding index in lower half block
2276 
-
2277  stateRealLo = stateVecReal[indexLo];
-
2278  stateImagLo = stateVecImag[indexLo];
-
2279 
-
2280  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2281  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2282  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2283  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2284  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2285 
-
2286  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2287  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2288  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2289  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2290  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2291  }
-
2292  }
-
2293  }
-
2294 
-
2295 }
+
2277  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2278  long long int thisTask;
+
2279  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2280  long long int chunkSize=qureg.numAmpsPerChunk;
+
2281  long long int chunkId=qureg.chunkId;
+
2282 
+
2283  // set dimensions
+
2284  sizeHalfBlock = 1LL << targetQubit;
+
2285  sizeBlock = 2LL * sizeHalfBlock;
+
2286 
+
2287  // Can't use qureg.stateVec as a private OMP var
+
2288  qreal *stateVecReal = qureg.stateVec.real;
+
2289  qreal *stateVecImag = qureg.stateVec.imag;
+
2290 
+
2291 # ifdef _OPENMP
+
2292 # pragma omp parallel \
+
2293  default (none) \
+
2294  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
+
2295  numTasks,chunkId,chunkSize) \
+
2296  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2297 # endif
+
2298  {
+
2299 # ifdef _OPENMP
+
2300 # pragma omp for schedule (static)
+
2301 # endif
+
2302  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2303 
+
2304  thisBlock = thisTask / sizeHalfBlock;
+
2305  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2306  indexLo = indexUp + sizeHalfBlock;
+
2307 
+
2308 
+
2309  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
+
2310  // if this equals the control mask, the control qubits have the desired values in the basis index
+
2311  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
+
2312  // store current state vector values in temp variables
+
2313  stateRealUp = stateVecReal[indexUp];
+
2314  stateImagUp = stateVecImag[indexUp];
+
2315 
+
2316  stateRealLo = stateVecReal[indexLo];
+
2317  stateImagLo = stateVecImag[indexLo];
+
2318 
+
2319  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2320  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2321  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2322  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2323  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2324 
+
2325  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2326  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2327  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2328  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2329  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2330  }
+
2331  }
+
2332  }
+
2333 
+
2334 }

References Qureg::chunkId, ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

-

Referenced by statevec_multiControlledUnitary().

+

Referenced by statevec_multiControlledUnitary().

@@ -7384,49 +7418,49 @@

-

Definition at line 3277 of file QuEST_cpu.c.

-
3278 {
-
3279  long long int index;
-
3280  long long int stateVecSize;
-
3281 
-
3282  long long int chunkSize=qureg.numAmpsPerChunk;
-
3283  long long int chunkId=qureg.chunkId;
-
3284 
-
3285  stateVecSize = qureg.numAmpsPerChunk;
-
3286  qreal *stateVecReal = qureg.stateVec.real;
-
3287  qreal *stateVecImag = qureg.stateVec.imag;
-
3288 
-
3289  qreal stateReal, stateImag;
-
3290  qreal cosAngle = cos(angle/2.0);
-
3291  qreal sinAngle = sin(angle/2.0);
-
3292 
-
3293  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3294  // exp(-angle/2 i fac_j)|j>
-
3295  int fac;
-
3296 
-
3297 # ifdef _OPENMP
-
3298 # pragma omp parallel \
-
3299  default (none) \
-
3300  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3301  private (index, fac, stateReal, stateImag)
-
3302 # endif
-
3303  {
-
3304 # ifdef _OPENMP
-
3305 # pragma omp for schedule (static)
-
3306 # endif
-
3307  for (index=0; index<stateVecSize; index++) {
-
3308  stateReal = stateVecReal[index];
-
3309  stateImag = stateVecImag[index];
-
3310 
-
3311  // odd-parity target qubits get fac_j = -1
-
3312  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
-
3313  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3314  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3315  }
-
3316  }
-
3317 }
+

Definition at line 3316 of file QuEST_cpu.c.

+
3317 {
+
3318  long long int index;
+
3319  long long int stateVecSize;
+
3320 
+
3321  long long int chunkSize=qureg.numAmpsPerChunk;
+
3322  long long int chunkId=qureg.chunkId;
+
3323 
+
3324  stateVecSize = qureg.numAmpsPerChunk;
+
3325  qreal *stateVecReal = qureg.stateVec.real;
+
3326  qreal *stateVecImag = qureg.stateVec.imag;
+
3327 
+
3328  qreal stateReal, stateImag;
+
3329  qreal cosAngle = cos(angle/2.0);
+
3330  qreal sinAngle = sin(angle/2.0);
+
3331 
+
3332  // = +-1, to flip sinAngle based on target qubit parity, to effect
+
3333  // exp(-angle/2 i fac_j)|j>
+
3334  int fac;
+
3335 
+
3336 # ifdef _OPENMP
+
3337 # pragma omp parallel \
+
3338  default (none) \
+
3339  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
+
3340  private (index, fac, stateReal, stateImag)
+
3341 # endif
+
3342  {
+
3343 # ifdef _OPENMP
+
3344 # pragma omp for schedule (static)
+
3345 # endif
+
3346  for (index=0; index<stateVecSize; index++) {
+
3347  stateReal = stateVecReal[index];
+
3348  stateImag = stateVecImag[index];
+
3349 
+
3350  // odd-parity target qubits get fac_j = -1
+
3351  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
+
3352  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
3353  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
3354  }
+
3355  }
+
3356 }
-

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -7476,35 +7510,35 @@

Definition at line 2612 of file QuEST_cpu.c.

-
2615 {
-
2616 
-
2617  long long int thisTask;
-
2618  long long int numTasks=qureg.numAmpsPerChunk;
-
2619 
-
2620  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2621  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2622 
-
2623 # ifdef _OPENMP
-
2624 # pragma omp parallel \
-
2625  default (none) \
-
2626  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
-
2627  private (thisTask)
-
2628 # endif
-
2629  {
-
2630 # ifdef _OPENMP
-
2631 # pragma omp for schedule (static)
-
2632 # endif
-
2633  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2634  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2635  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2636  }
-
2637  }
-
2638 }
+

Definition at line 2651 of file QuEST_cpu.c.

+
2654 {
+
2655 
+
2656  long long int thisTask;
+
2657  long long int numTasks=qureg.numAmpsPerChunk;
+
2658 
+
2659  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2660  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2661 
+
2662 # ifdef _OPENMP
+
2663 # pragma omp parallel \
+
2664  default (none) \
+
2665  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
+
2666  private (thisTask)
+
2667 # endif
+
2668  {
+
2669 # ifdef _OPENMP
+
2670 # pragma omp for schedule (static)
+
2671 # endif
+
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2673  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
+
2674  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
+
2675  }
+
2676  }
+
2677 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_pauliX().

+

Referenced by statevec_pauliX().

@@ -7534,55 +7568,55 @@

-

Definition at line 2554 of file QuEST_cpu.c.

-
2555 {
-
2556  long long int sizeBlock, sizeHalfBlock;
-
2557  long long int thisBlock, // current block
-
2558  indexUp,indexLo; // current index and corresponding index in lower half block
-
2559 
-
2560  qreal stateRealUp,stateImagUp;
-
2561  long long int thisTask;
-
2562  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2563 
-
2564  // set dimensions
-
2565  sizeHalfBlock = 1LL << targetQubit;
-
2566  sizeBlock = 2LL * sizeHalfBlock;
-
2567 
-
2568  // Can't use qureg.stateVec as a private OMP var
-
2569  qreal *stateVecReal = qureg.stateVec.real;
-
2570  qreal *stateVecImag = qureg.stateVec.imag;
-
2571 
-
2572 # ifdef _OPENMP
-
2573 # pragma omp parallel \
-
2574  default (none) \
-
2575  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
-
2576  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2577 # endif
-
2578  {
-
2579 # ifdef _OPENMP
-
2580 # pragma omp for schedule (static)
-
2581 # endif
-
2582  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2583  thisBlock = thisTask / sizeHalfBlock;
-
2584  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2585  indexLo = indexUp + sizeHalfBlock;
-
2586 
-
2587  stateRealUp = stateVecReal[indexUp];
-
2588  stateImagUp = stateVecImag[indexUp];
-
2589 
-
2590  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2591  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2592 
-
2593  stateVecReal[indexLo] = stateRealUp;
-
2594  stateVecImag[indexLo] = stateImagUp;
-
2595  }
-
2596  }
-
2597 
-
2598 }
+

Definition at line 2593 of file QuEST_cpu.c.

+
2594 {
+
2595  long long int sizeBlock, sizeHalfBlock;
+
2596  long long int thisBlock, // current block
+
2597  indexUp,indexLo; // current index and corresponding index in lower half block
+
2598 
+
2599  qreal stateRealUp,stateImagUp;
+
2600  long long int thisTask;
+
2601  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2602 
+
2603  // set dimensions
+
2604  sizeHalfBlock = 1LL << targetQubit;
+
2605  sizeBlock = 2LL * sizeHalfBlock;
+
2606 
+
2607  // Can't use qureg.stateVec as a private OMP var
+
2608  qreal *stateVecReal = qureg.stateVec.real;
+
2609  qreal *stateVecImag = qureg.stateVec.imag;
+
2610 
+
2611 # ifdef _OPENMP
+
2612 # pragma omp parallel \
+
2613  default (none) \
+
2614  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
+
2615  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
+
2616 # endif
+
2617  {
+
2618 # ifdef _OPENMP
+
2619 # pragma omp for schedule (static)
+
2620 # endif
+
2621  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2622  thisBlock = thisTask / sizeHalfBlock;
+
2623  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2624  indexLo = indexUp + sizeHalfBlock;
+
2625 
+
2626  stateRealUp = stateVecReal[indexUp];
+
2627  stateImagUp = stateVecImag[indexUp];
+
2628 
+
2629  stateVecReal[indexUp] = stateVecReal[indexLo];
+
2630  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2631 
+
2632  stateVecReal[indexLo] = stateRealUp;
+
2633  stateVecImag[indexLo] = stateImagUp;
+
2634  }
+
2635  }
+
2636 
+
2637 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_pauliX().

+

Referenced by statevec_pauliX().

@@ -7646,40 +7680,40 @@

Definition at line 2906 of file QuEST_cpu.c.

-
2910 {
-
2911 
-
2912  long long int thisTask;
-
2913  long long int numTasks=qureg.numAmpsPerChunk;
-
2914 
-
2915  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2916  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2917 
-
2918  int realSign=1, imagSign=1;
-
2919  if (updateUpper) imagSign=-1;
-
2920  else realSign = -1;
-
2921 
-
2922 # ifdef _OPENMP
-
2923 # pragma omp parallel \
-
2924  default (none) \
-
2925  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2926  realSign,imagSign, numTasks,conjFac) \
-
2927  private (thisTask)
-
2928 # endif
-
2929  {
-
2930 # ifdef _OPENMP
-
2931 # pragma omp for schedule (static)
-
2932 # endif
-
2933  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2934  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
-
2935  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
-
2936  }
-
2937  }
-
2938 }
+

Definition at line 2945 of file QuEST_cpu.c.

+
2949 {
+
2950 
+
2951  long long int thisTask;
+
2952  long long int numTasks=qureg.numAmpsPerChunk;
+
2953 
+
2954  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2955  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2956 
+
2957  int realSign=1, imagSign=1;
+
2958  if (updateUpper) imagSign=-1;
+
2959  else realSign = -1;
+
2960 
+
2961 # ifdef _OPENMP
+
2962 # pragma omp parallel \
+
2963  default (none) \
+
2964  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
2965  realSign,imagSign, numTasks,conjFac) \
+
2966  private (thisTask)
+
2967 # endif
+
2968  {
+
2969 # ifdef _OPENMP
+
2970 # pragma omp for schedule (static)
+
2971 # endif
+
2972  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2973  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
+
2974  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
+
2975  }
+
2976  }
+
2977 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_pauliY(), and statevec_pauliYConj().

+

Referenced by statevec_pauliY(), and statevec_pauliYConj().

@@ -7715,53 +7749,53 @@

-

Definition at line 2848 of file QuEST_cpu.c.

-
2849 {
-
2850  long long int sizeBlock, sizeHalfBlock;
-
2851  long long int thisBlock, // current block
-
2852  indexUp,indexLo; // current index and corresponding index in lower half block
-
2853 
-
2854  qreal stateRealUp,stateImagUp;
-
2855  long long int thisTask;
-
2856  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2857 
-
2858  // set dimensions
-
2859  sizeHalfBlock = 1LL << targetQubit;
-
2860  sizeBlock = 2LL * sizeHalfBlock;
-
2861 
-
2862  // Can't use qureg.stateVec as a private OMP var
-
2863  qreal *stateVecReal = qureg.stateVec.real;
-
2864  qreal *stateVecImag = qureg.stateVec.imag;
-
2865 
-
2866 # ifdef _OPENMP
-
2867 # pragma omp parallel \
-
2868  default (none) \
-
2869  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
-
2870  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2871 # endif
-
2872  {
-
2873 # ifdef _OPENMP
-
2874 # pragma omp for schedule (static)
-
2875 # endif
-
2876  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2877  thisBlock = thisTask / sizeHalfBlock;
-
2878  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2879  indexLo = indexUp + sizeHalfBlock;
-
2880 
-
2881  stateRealUp = stateVecReal[indexUp];
-
2882  stateImagUp = stateVecImag[indexUp];
-
2883 
-
2884  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2885  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2886  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2887  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2888  }
-
2889  }
-
2890 }
+

Definition at line 2887 of file QuEST_cpu.c.

+
2888 {
+
2889  long long int sizeBlock, sizeHalfBlock;
+
2890  long long int thisBlock, // current block
+
2891  indexUp,indexLo; // current index and corresponding index in lower half block
+
2892 
+
2893  qreal stateRealUp,stateImagUp;
+
2894  long long int thisTask;
+
2895  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2896 
+
2897  // set dimensions
+
2898  sizeHalfBlock = 1LL << targetQubit;
+
2899  sizeBlock = 2LL * sizeHalfBlock;
+
2900 
+
2901  // Can't use qureg.stateVec as a private OMP var
+
2902  qreal *stateVecReal = qureg.stateVec.real;
+
2903  qreal *stateVecImag = qureg.stateVec.imag;
+
2904 
+
2905 # ifdef _OPENMP
+
2906 # pragma omp parallel \
+
2907  default (none) \
+
2908  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
+
2909  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
+
2910 # endif
+
2911  {
+
2912 # ifdef _OPENMP
+
2913 # pragma omp for schedule (static)
+
2914 # endif
+
2915  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2916  thisBlock = thisTask / sizeHalfBlock;
+
2917  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2918  indexLo = indexUp + sizeHalfBlock;
+
2919 
+
2920  stateRealUp = stateVecReal[indexUp];
+
2921  stateImagUp = stateVecImag[indexUp];
+
2922 
+
2923  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
2924  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
2925  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
2926  stateVecImag[indexLo] = conjFac * stateRealUp;
+
2927  }
+
2928  }
+
2929 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_pauliY(), and statevec_pauliYConj().

+

Referenced by statevec_pauliY(), and statevec_pauliYConj().

@@ -7797,46 +7831,46 @@

-

Definition at line 3146 of file QuEST_cpu.c.

-
3147 {
-
3148  long long int index;
-
3149  long long int stateVecSize;
-
3150  int targetBit;
-
3151 
-
3152  long long int chunkSize=qureg.numAmpsPerChunk;
-
3153  long long int chunkId=qureg.chunkId;
-
3154 
-
3155  // dimension of the state vector
-
3156  stateVecSize = qureg.numAmpsPerChunk;
-
3157  qreal *stateVecReal = qureg.stateVec.real;
-
3158  qreal *stateVecImag = qureg.stateVec.imag;
-
3159 
-
3160  qreal stateRealLo, stateImagLo;
-
3161  qreal cosAngle = term.real;
-
3162  qreal sinAngle = term.imag;
-
3163 
-
3164 # ifdef _OPENMP
-
3165 # pragma omp parallel for \
-
3166  default (none) \
-
3167  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
-
3168  chunkId,chunkSize,targetQubit) \
-
3169  private (index,targetBit,stateRealLo,stateImagLo) \
-
3170  schedule (static)
-
3171 # endif
-
3172  for (index=0; index<stateVecSize; index++) {
-
3173 
-
3174  // update the coeff of the |1> state of the target qubit
-
3175  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
-
3176  if (targetBit) {
-
3177 
-
3178  stateRealLo = stateVecReal[index];
-
3179  stateImagLo = stateVecImag[index];
-
3180 
-
3181  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3182  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3183  }
-
3184  }
-
3185 }
+

Definition at line 3185 of file QuEST_cpu.c.

+
3186 {
+
3187  long long int index;
+
3188  long long int stateVecSize;
+
3189  int targetBit;
+
3190 
+
3191  long long int chunkSize=qureg.numAmpsPerChunk;
+
3192  long long int chunkId=qureg.chunkId;
+
3193 
+
3194  // dimension of the state vector
+
3195  stateVecSize = qureg.numAmpsPerChunk;
+
3196  qreal *stateVecReal = qureg.stateVec.real;
+
3197  qreal *stateVecImag = qureg.stateVec.imag;
+
3198 
+
3199  qreal stateRealLo, stateImagLo;
+
3200  qreal cosAngle = term.real;
+
3201  qreal sinAngle = term.imag;
+
3202 
+
3203 # ifdef _OPENMP
+
3204 # pragma omp parallel for \
+
3205  default (none) \
+
3206  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
+
3207  chunkId,chunkSize,targetQubit) \
+
3208  private (index,targetBit,stateRealLo,stateImagLo) \
+
3209  schedule (static)
+
3210 # endif
+
3211  for (index=0; index<stateVecSize; index++) {
+
3212 
+
3213  // update the coeff of the |1> state of the target qubit
+
3214  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
+
3215  if (targetBit) {
+
3216 
+
3217  stateRealLo = stateVecReal[index];
+
3218  stateImagLo = stateVecImag[index];
+
3219 
+
3220  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3221  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3222  }
+
3223  }
+
3224 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

@@ -7874,33 +7908,33 @@

-

Definition at line 1428 of file QuEST_cpu.c.

-
1428  {
-
1429  long long int index;
-
1430  int rank;
-
1431  if (qureg.numQubitsInStateVec<=5){
-
1432  for (rank=0; rank<qureg.numChunks; rank++){
-
1433  if (qureg.chunkId==rank){
-
1434  if (reportRank) {
-
1435  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
1436  printf("real, imag\n");
-
1437  } else if (rank==0) {
-
1438  printf("Reporting state [\n");
-
1439  printf("real, imag\n");
-
1440  }
-
1441 
-
1442  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
1443  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
-
1444  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
1445  }
-
1446  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
1447  }
-
1448  syncQuESTEnv(env);
-
1449  }
-
1450  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
-
1451 }
+

Definition at line 1439 of file QuEST_cpu.c.

+
1439  {
+
1440  long long int index;
+
1441  int rank;
+
1442  if (qureg.numQubitsInStateVec<=5){
+
1443  for (rank=0; rank<qureg.numChunks; rank++){
+
1444  if (qureg.chunkId==rank){
+
1445  if (reportRank) {
+
1446  printf("Reporting state from rank %d [\n", qureg.chunkId);
+
1447  printf("real, imag\n");
+
1448  } else if (rank==0) {
+
1449  printf("Reporting state [\n");
+
1450  printf("real, imag\n");
+
1451  }
+
1452 
+
1453  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
1454  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
+
1455  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
1456  }
+
1457  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
+
1458  }
+
1459  syncQuESTEnv(env);
+
1460  }
+
1461  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
+
1462 }
-

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

+

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

@@ -7948,48 +7982,48 @@

-

Definition at line 1237 of file QuEST_cpu.c.

-
1237  {
-
1238 
-
1239  /* this is actually distributed, since the user's code runs on every node */
-
1240 
-
1241  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
1242  // these may be negative or above qureg.numAmpsPerChunk
-
1243  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
-
1244  long long int localEndInd = localStartInd + numAmps; // exclusive
-
1245 
-
1246  // add this to a local index to get corresponding elem in reals & imags
-
1247  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
-
1248 
-
1249  // restrict these indices to fit into this chunk
-
1250  if (localStartInd < 0)
-
1251  localStartInd = 0;
-
1252  if (localEndInd > qureg.numAmpsPerChunk)
-
1253  localEndInd = qureg.numAmpsPerChunk;
-
1254  // they may now be out of order = no iterations
-
1255 
-
1256  // unpacking OpenMP vars
-
1257  long long int index;
-
1258  qreal* vecRe = qureg.stateVec.real;
-
1259  qreal* vecIm = qureg.stateVec.imag;
-
1260 
-
1261 # ifdef _OPENMP
-
1262 # pragma omp parallel \
-
1263  default (none) \
-
1264  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
-
1265  private (index)
-
1266 # endif
-
1267  {
-
1268 # ifdef _OPENMP
-
1269 # pragma omp for schedule (static)
-
1270 # endif
-
1271  // iterate these local inds - this might involve no iterations
-
1272  for (index=localStartInd; index < localEndInd; index++) {
-
1273  vecRe[index] = reals[index + offset];
-
1274  vecIm[index] = imags[index + offset];
-
1275  }
-
1276  }
-
1277 }
+

Definition at line 1248 of file QuEST_cpu.c.

+
1248  {
+
1249 
+
1250  /* this is actually distributed, since the user's code runs on every node */
+
1251 
+
1252  // local start/end indices of the given amplitudes, assuming they fit in this chunk
+
1253  // these may be negative or above qureg.numAmpsPerChunk
+
1254  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
+
1255  long long int localEndInd = localStartInd + numAmps; // exclusive
+
1256 
+
1257  // add this to a local index to get corresponding elem in reals & imags
+
1258  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
+
1259 
+
1260  // restrict these indices to fit into this chunk
+
1261  if (localStartInd < 0)
+
1262  localStartInd = 0;
+
1263  if (localEndInd > qureg.numAmpsPerChunk)
+
1264  localEndInd = qureg.numAmpsPerChunk;
+
1265  // they may now be out of order = no iterations
+
1266 
+
1267  // unpacking OpenMP vars
+
1268  long long int index;
+
1269  qreal* vecRe = qureg.stateVec.real;
+
1270  qreal* vecIm = qureg.stateVec.imag;
+
1271 
+
1272 # ifdef _OPENMP
+
1273 # pragma omp parallel \
+
1274  default (none) \
+
1275  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
+
1276  private (index)
+
1277 # endif
+
1278  {
+
1279 # ifdef _OPENMP
+
1280 # pragma omp for schedule (static)
+
1281 # endif
+
1282  // iterate these local inds - this might involve no iterations
+
1283  for (index=localStartInd; index < localEndInd; index++) {
+
1284  vecRe[index] = reals[index + offset];
+
1285  vecIm[index] = imags[index + offset];
+
1286  }
+
1287  }
+
1288 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -8045,48 +8079,48 @@

-

Definition at line 3965 of file QuEST_cpu.c.

-
3965  {
-
3966 
-
3967  long long int numAmps = qureg1.numAmpsPerChunk;
-
3968 
-
3969  qreal *vecRe1 = qureg1.stateVec.real;
-
3970  qreal *vecIm1 = qureg1.stateVec.imag;
-
3971  qreal *vecRe2 = qureg2.stateVec.real;
-
3972  qreal *vecIm2 = qureg2.stateVec.imag;
-
3973  qreal *vecReOut = out.stateVec.real;
-
3974  qreal *vecImOut = out.stateVec.imag;
-
3975 
-
3976  qreal facRe1 = fac1.real;
-
3977  qreal facIm1 = fac1.imag;
-
3978  qreal facRe2 = fac2.real;
-
3979  qreal facIm2 = fac2.imag;
-
3980  qreal facReOut = facOut.real;
-
3981  qreal facImOut = facOut.imag;
-
3982 
-
3983  qreal re1,im1, re2,im2, reOut,imOut;
-
3984  long long int index;
-
3985 
-
3986 # ifdef _OPENMP
-
3987 # pragma omp parallel \
-
3988  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
-
3989  private (index, re1,im1, re2,im2, reOut,imOut)
-
3990 # endif
-
3991  {
-
3992 # ifdef _OPENMP
-
3993 # pragma omp for schedule (static)
-
3994 # endif
-
3995  for (index=0LL; index<numAmps; index++) {
-
3996  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3997  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3998  reOut = vecReOut[index];
-
3999  imOut = vecImOut[index];
-
4000 
-
4001  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
4002  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
4003  }
-
4004  }
-
4005 }
+

Definition at line 4005 of file QuEST_cpu.c.

+
4005  {
+
4006 
+
4007  long long int numAmps = qureg1.numAmpsPerChunk;
+
4008 
+
4009  qreal *vecRe1 = qureg1.stateVec.real;
+
4010  qreal *vecIm1 = qureg1.stateVec.imag;
+
4011  qreal *vecRe2 = qureg2.stateVec.real;
+
4012  qreal *vecIm2 = qureg2.stateVec.imag;
+
4013  qreal *vecReOut = out.stateVec.real;
+
4014  qreal *vecImOut = out.stateVec.imag;
+
4015 
+
4016  qreal facRe1 = fac1.real;
+
4017  qreal facIm1 = fac1.imag;
+
4018  qreal facRe2 = fac2.real;
+
4019  qreal facIm2 = fac2.imag;
+
4020  qreal facReOut = facOut.real;
+
4021  qreal facImOut = facOut.imag;
+
4022 
+
4023  qreal re1,im1, re2,im2, reOut,imOut;
+
4024  long long int index;
+
4025 
+
4026 # ifdef _OPENMP
+
4027 # pragma omp parallel \
+
4028  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
+
4029  private (index, re1,im1, re2,im2, reOut,imOut)
+
4030 # endif
+
4031  {
+
4032 # ifdef _OPENMP
+
4033 # pragma omp for schedule (static)
+
4034 # endif
+
4035  for (index=0LL; index<numAmps; index++) {
+
4036  re1 = vecRe1[index]; im1 = vecIm1[index];
+
4037  re2 = vecRe2[index]; im2 = vecIm2[index];
+
4038  reOut = vecReOut[index];
+
4039  imOut = vecImOut[index];
+
4040 
+
4041  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
+
4042  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
+
4043  }
+
4044  }
+
4045 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

@@ -8132,50 +8166,50 @@

Definition at line 3925 of file QuEST_cpu.c.

-
3925  {
-
3926 
-
3927  // can't use qureg.stateVec as a private OMP var
-
3928  qreal *reVec = qureg.stateVec.real;
-
3929  qreal *imVec = qureg.stateVec.imag;
-
3930  qreal *rePairVec = qureg.pairStateVec.real;
-
3931  qreal *imPairVec = qureg.pairStateVec.imag;
-
3932 
-
3933  long long int numLocalAmps = qureg.numAmpsPerChunk;
-
3934  long long int globalStartInd = qureg.chunkId * numLocalAmps;
-
3935  long long int pairGlobalStartInd = pairRank * numLocalAmps;
-
3936 
-
3937  long long int localInd, globalInd;
-
3938  long long int pairLocalInd, pairGlobalInd;
-
3939 
-
3940 # ifdef _OPENMP
-
3941 # pragma omp parallel \
-
3942  default (none) \
-
3943  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
-
3944  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
-
3945 # endif
-
3946  {
-
3947 # ifdef _OPENMP
-
3948 # pragma omp for schedule (static)
-
3949 # endif
-
3950  for (localInd=0; localInd < numLocalAmps; localInd++) {
-
3951 
-
3952  globalInd = globalStartInd + localInd;
-
3953  if (isOddParity(globalInd, qb1, qb2)) {
-
3954 
-
3955  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
-
3956  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
-
3957 
-
3958  reVec[localInd] = rePairVec[pairLocalInd];
-
3959  imVec[localInd] = imPairVec[pairLocalInd];
-
3960  }
-
3961  }
-
3962  }
-
3963 }
+

Definition at line 3965 of file QuEST_cpu.c.

+
3965  {
+
3966 
+
3967  // can't use qureg.stateVec as a private OMP var
+
3968  qreal *reVec = qureg.stateVec.real;
+
3969  qreal *imVec = qureg.stateVec.imag;
+
3970  qreal *rePairVec = qureg.pairStateVec.real;
+
3971  qreal *imPairVec = qureg.pairStateVec.imag;
+
3972 
+
3973  long long int numLocalAmps = qureg.numAmpsPerChunk;
+
3974  long long int globalStartInd = qureg.chunkId * numLocalAmps;
+
3975  long long int pairGlobalStartInd = pairRank * numLocalAmps;
+
3976 
+
3977  long long int localInd, globalInd;
+
3978  long long int pairLocalInd, pairGlobalInd;
+
3979 
+
3980 # ifdef _OPENMP
+
3981 # pragma omp parallel \
+
3982  default (none) \
+
3983  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
+
3984  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
+
3985 # endif
+
3986  {
+
3987 # ifdef _OPENMP
+
3988 # pragma omp for schedule (static)
+
3989 # endif
+
3990  for (localInd=0; localInd < numLocalAmps; localInd++) {
+
3991 
+
3992  globalInd = globalStartInd + localInd;
+
3993  if (isOddParity(globalInd, qb1, qb2)) {
+
3994 
+
3995  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
+
3996  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
+
3997 
+
3998  reVec[localInd] = rePairVec[pairLocalInd];
+
3999  imVec[localInd] = imPairVec[pairLocalInd];
+
4000  }
+
4001  }
+
4002  }
+
4003 }

References Qureg::chunkId, flipBit(), isOddParity(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by statevec_swapQubitAmps().

+

Referenced by statevec_swapQubitAmps().

@@ -8214,49 +8248,49 @@

-

Definition at line 3882 of file QuEST_cpu.c.

-
3882  {
-
3883 
-
3884  // can't use qureg.stateVec as a private OMP var
-
3885  qreal *reVec = qureg.stateVec.real;
-
3886  qreal *imVec = qureg.stateVec.imag;
-
3887 
-
3888  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
3889  long long int thisTask;
-
3890  long long int ind00, ind01, ind10;
-
3891  qreal re01, re10;
-
3892  qreal im01, im10;
-
3893 
-
3894 # ifdef _OPENMP
-
3895 # pragma omp parallel \
-
3896  default (none) \
-
3897  shared (reVec,imVec,numTasks,qb1,qb2) \
-
3898  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
-
3899 # endif
-
3900  {
-
3901 # ifdef _OPENMP
-
3902 # pragma omp for schedule (static)
-
3903 # endif
-
3904  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3905  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
3906  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
3907  ind01 = flipBit(ind00, qb1);
-
3908  ind10 = flipBit(ind00, qb2);
-
3909 
-
3910  // extract statevec amplitudes
-
3911  re01 = reVec[ind01]; im01 = imVec[ind01];
-
3912  re10 = reVec[ind10]; im10 = imVec[ind10];
-
3913 
-
3914  // swap 01 and 10 amps
-
3915  reVec[ind01] = re10; reVec[ind10] = re01;
-
3916  imVec[ind01] = im10; imVec[ind10] = im01;
-
3917  }
-
3918  }
-
3919 }
+

Definition at line 3922 of file QuEST_cpu.c.

+
3922  {
+
3923 
+
3924  // can't use qureg.stateVec as a private OMP var
+
3925  qreal *reVec = qureg.stateVec.real;
+
3926  qreal *imVec = qureg.stateVec.imag;
+
3927 
+
3928  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
+
3929  long long int thisTask;
+
3930  long long int ind00, ind01, ind10;
+
3931  qreal re01, re10;
+
3932  qreal im01, im10;
+
3933 
+
3934 # ifdef _OPENMP
+
3935 # pragma omp parallel \
+
3936  default (none) \
+
3937  shared (reVec,imVec,numTasks,qb1,qb2) \
+
3938  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
+
3939 # endif
+
3940  {
+
3941 # ifdef _OPENMP
+
3942 # pragma omp for schedule (static)
+
3943 # endif
+
3944  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3945  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
+
3946  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
+
3947  ind01 = flipBit(ind00, qb1);
+
3948  ind10 = flipBit(ind00, qb2);
+
3949 
+
3950  // extract statevec amplitudes
+
3951  re01 = reVec[ind01]; im01 = imVec[ind01];
+
3952  re10 = reVec[ind10]; im10 = imVec[ind10];
+
3953 
+
3954  // swap 01 and 10 amps
+
3955  reVec[ind01] = re10; reVec[ind10] = re01;
+
3956  imVec[ind01] = im10; imVec[ind10] = im01;
+
3957  }
+
3958  }
+
3959 }

References flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_swapQubitAmps().

+

Referenced by statevec_swapQubitAmps().

@@ -8325,50 +8359,50 @@

Definition at line 2112 of file QuEST_cpu.c.

-
2117 {
-
2118 
-
2119  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2120  long long int thisTask;
-
2121  long long int numTasks=qureg.numAmpsPerChunk;
-
2122 
-
2123  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2124  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2125  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2126  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2127  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2128 
-
2129 
-
2130 # ifdef _OPENMP
-
2131 # pragma omp parallel \
-
2132  default (none) \
-
2133  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2134  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
-
2135  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2136 # endif
-
2137  {
-
2138 # ifdef _OPENMP
-
2139 # pragma omp for schedule (static)
-
2140 # endif
-
2141  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2142  // store current state vector values in temp variables
-
2143  stateRealUp = stateVecRealUp[thisTask];
-
2144  stateImagUp = stateVecImagUp[thisTask];
-
2145 
-
2146  stateRealLo = stateVecRealLo[thisTask];
-
2147  stateImagLo = stateVecImagLo[thisTask];
-
2148 
-
2149  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2150  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2151  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2152  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2153  }
-
2154  }
-
2155 }
+

Definition at line 2151 of file QuEST_cpu.c.

+
2156 {
+
2157 
+
2158  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2159  long long int thisTask;
+
2160  long long int numTasks=qureg.numAmpsPerChunk;
+
2161 
+
2162  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2163  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2164  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2165  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2166  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2167 
+
2168 
+
2169 # ifdef _OPENMP
+
2170 # pragma omp parallel \
+
2171  default (none) \
+
2172  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2173  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
+
2174  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2175 # endif
+
2176  {
+
2177 # ifdef _OPENMP
+
2178 # pragma omp for schedule (static)
+
2179 # endif
+
2180  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2181  // store current state vector values in temp variables
+
2182  stateRealUp = stateVecRealUp[thisTask];
+
2183  stateImagUp = stateVecImagUp[thisTask];
+
2184 
+
2185  stateRealLo = stateVecRealLo[thisTask];
+
2186  stateImagLo = stateVecImagLo[thisTask];
+
2187 
+
2188  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2189  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2190  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2191  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2192  }
+
2193  }
+
2194 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_unitary().

+

Referenced by statevec_unitary().

@@ -8404,67 +8438,67 @@

-

Definition at line 1987 of file QuEST_cpu.c.

-
1988 {
-
1989  long long int sizeBlock, sizeHalfBlock;
-
1990  long long int thisBlock, // current block
-
1991  indexUp,indexLo; // current index and corresponding index in lower half block
-
1992 
-
1993  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1994  long long int thisTask;
-
1995  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1996 
-
1997  // set dimensions
-
1998  sizeHalfBlock = 1LL << targetQubit;
-
1999  sizeBlock = 2LL * sizeHalfBlock;
-
2000 
-
2001  // Can't use qureg.stateVec as a private OMP var
-
2002  qreal *stateVecReal = qureg.stateVec.real;
-
2003  qreal *stateVecImag = qureg.stateVec.imag;
-
2004 
-
2005 # ifdef _OPENMP
-
2006 # pragma omp parallel \
-
2007  default (none) \
-
2008  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
-
2009  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2010 # endif
-
2011  {
-
2012 # ifdef _OPENMP
-
2013 # pragma omp for schedule (static)
-
2014 # endif
-
2015  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2016 
-
2017  thisBlock = thisTask / sizeHalfBlock;
-
2018  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2019  indexLo = indexUp + sizeHalfBlock;
-
2020 
-
2021  // store current state vector values in temp variables
-
2022  stateRealUp = stateVecReal[indexUp];
-
2023  stateImagUp = stateVecImag[indexUp];
-
2024 
-
2025  stateRealLo = stateVecReal[indexLo];
-
2026  stateImagLo = stateVecImag[indexLo];
-
2027 
-
2028 
-
2029  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2030  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2031  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2032  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2033  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2034 
-
2035  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2036  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2037  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2038  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2039  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2040 
-
2041  }
-
2042  }
-
2043 }
+

Definition at line 2026 of file QuEST_cpu.c.

+
2027 {
+
2028  long long int sizeBlock, sizeHalfBlock;
+
2029  long long int thisBlock, // current block
+
2030  indexUp,indexLo; // current index and corresponding index in lower half block
+
2031 
+
2032  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2033  long long int thisTask;
+
2034  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2035 
+
2036  // set dimensions
+
2037  sizeHalfBlock = 1LL << targetQubit;
+
2038  sizeBlock = 2LL * sizeHalfBlock;
+
2039 
+
2040  // Can't use qureg.stateVec as a private OMP var
+
2041  qreal *stateVecReal = qureg.stateVec.real;
+
2042  qreal *stateVecImag = qureg.stateVec.imag;
+
2043 
+
2044 # ifdef _OPENMP
+
2045 # pragma omp parallel \
+
2046  default (none) \
+
2047  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
+
2048  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2049 # endif
+
2050  {
+
2051 # ifdef _OPENMP
+
2052 # pragma omp for schedule (static)
+
2053 # endif
+
2054  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2055 
+
2056  thisBlock = thisTask / sizeHalfBlock;
+
2057  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2058  indexLo = indexUp + sizeHalfBlock;
+
2059 
+
2060  // store current state vector values in temp variables
+
2061  stateRealUp = stateVecReal[indexUp];
+
2062  stateImagUp = stateVecImag[indexUp];
+
2063 
+
2064  stateRealLo = stateVecReal[indexLo];
+
2065  stateImagLo = stateVecImag[indexLo];
+
2066 
+
2067 
+
2068  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2069  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2070  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2071  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2072  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2073 
+
2074  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2075  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2076  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2077  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2078  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2079 
+
2080  }
+
2081  }
+
2082 }

References ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

-

Referenced by statevec_unitary().

+

Referenced by statevec_unitary().

@@ -8500,45 +8534,45 @@

-

Definition at line 734 of file QuEST_cpu.c.

-
734  {
-
735  long long int i;
-
736 # ifdef _OPENMP
-
737 # pragma omp parallel for schedule (static)
-
738 # endif
-
739  for (i=startInd; i < startInd+numAmps; i++) {
-
740  qureg.stateVec.real[i] = 0;
-
741  qureg.stateVec.imag[i] = 0;
-
742  }
-
743 }
+

Definition at line 740 of file QuEST_cpu.c.

+
740  {
+
741  long long int i;
+
742 # ifdef _OPENMP
+
743 # pragma omp parallel for schedule (static)
+
744 # endif
+
745  for (i=startInd; i < startInd+numAmps; i++) {
+
746  qureg.stateVec.real[i] = 0;
+
747  qureg.stateVec.imag[i] = 0;
+
748  }
+
749 }

References Qureg::stateVec.

-

Referenced by alternateNormZeroingSomeAmpBlocks(), and densmatr_collapseToKnownProbOutcome().

+

Referenced by alternateNormZeroingSomeAmpBlocks(), and densmatr_collapseToKnownProbOutcome().

@ INVERSE_PRODUCT
Definition: QuEST.h:233
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1897
+
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1908
qreal real[4][4]
Definition: QuEST.h:177
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
@ PAULI_Z
Definition: QuEST.h:96
@ DISTANCE
Definition: QuEST.h:234
-
int rank
Definition: QuEST.h:363
+
int rank
Definition: QuEST.h:364
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:304
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
-
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3268
+
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3307
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:306
@ NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
@ UNSIGNED
Definition: QuEST.h:269
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
@ INVERSE_DISTANCE
Definition: QuEST.h:234
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:85
#define qreal
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
@@ -8548,17 +8582,17 @@

qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
+
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:54
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
@ SCALED_PRODUCT
Definition: QuEST.h:233
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
-
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:754
-
int numRanks
Definition: QuEST.h:364
+
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:760
+
int numRanks
Definition: QuEST.h:365
qreal imag[4][4]
Definition: QuEST.h:178
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:744
+
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:750
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
qreal ** real
Definition: QuEST.h:189
@@ -8584,7 +8618,7 @@

Represents one complex number.
Definition: QuEST.h:103
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:734
+
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:740
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
diff --git a/docs/QuEST__cpu_8c_source.html b/docs/QuEST__cpu_8c_source.html index 74a52f186..fb977129b 100644 --- a/docs/QuEST__cpu_8c_source.html +++ b/docs/QuEST__cpu_8c_source.html @@ -27,7 +27,7 @@ @@ -77,3191 +77,3191 @@
27 # include <omp.h>
28 # endif
29 
-
30 
-
31 
-
32 /*
-
33  * overloads for consistent API with GPU
-
34  */
-
35 
-
36 void copyStateToGPU(Qureg qureg) {
-
37 }
-
38 
-
39 void copyStateFromGPU(Qureg qureg) {
-
40 }
+
30 /* to support MSVC, we must remove the use of VLA in multiQubtUnitary.
+
31  * We'll instead create stack arrays use _malloca
+
32  */
+
33 #ifdef _WIN32
+
34  #include <malloc.h>
+
35 #endif
+
36 
+
37 
+
38 /*
+
39  * overloads for consistent API with GPU
+
40  */
41 
-
42 
-
43 
-
44 /*
-
45  * state vector and density matrix operations
-
46  */
+
42 void copyStateToGPU(Qureg qureg) {
+
43 }
+
44 
+
45 void copyStateFromGPU(Qureg qureg) {
+
46 }
47 
-
48 void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain){
-
49  long long int numTasks = qureg.numAmpsPerChunk;
-
50  long long int innerMask = 1LL << targetQubit;
-
51  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
52 
-
53  long long int thisTask;
-
54  long long int thisPattern;
-
55  long long int totMask = innerMask|outerMask;
-
56 
-
57 # ifdef _OPENMP
-
58 # pragma omp parallel \
-
59  default (none) \
-
60  shared (innerMask,outerMask,totMask,qureg,retain,numTasks, targetQubit) \
-
61  private (thisTask,thisPattern)
-
62 # endif
-
63  {
-
64 # ifdef _OPENMP
-
65 # pragma omp for schedule (static)
-
66 # endif
-
67  for (thisTask=0; thisTask<numTasks; thisTask++){
-
68  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
69  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
70  // do dephase
-
71  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
72  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
73  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
74  }
-
75  }
-
76  }
-
77 }
-
78 
-
79 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) {
-
80  qreal retain=1-dephase;
-
81  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
-
82 }
-
83 
-
84 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) {
-
85  qreal retain=1-dephase;
-
86 
-
87  long long int numTasks = qureg.numAmpsPerChunk;
-
88  long long int innerMaskQubit1 = 1LL << qubit1;
-
89  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
-
90  long long int innerMaskQubit2 = 1LL << qubit2;
-
91  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
-
92  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
-
93  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
-
94 
-
95  long long int thisTask;
-
96  long long int thisPatternQubit1, thisPatternQubit2;
-
97 
-
98 # ifdef _OPENMP
-
99 # pragma omp parallel \
-
100  default (none) \
-
101  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
-
102  totMaskQubit2,qureg,retain,numTasks) \
-
103  private (thisTask,thisPatternQubit1,thisPatternQubit2)
-
104 # endif
-
105  {
-
106 # ifdef _OPENMP
-
107 # pragma omp for schedule (static)
-
108 # endif
-
109  for (thisTask=0; thisTask<numTasks; thisTask++){
-
110  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
111  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
112 
-
113  // any mismatch |...0...><...1...| etc
-
114  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
-
115  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
-
116  // do dephase
-
117  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
118  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
119  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
120  }
-
121  }
-
122  }
-
123 }
-
124 
-
125 void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel) {
-
126  qreal retain=1-depolLevel;
-
127 
-
128  long long int numTasks = qureg.numAmpsPerChunk;
-
129  long long int innerMask = 1LL << targetQubit;
-
130  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
131  long long int totMask = innerMask|outerMask;
-
132 
-
133  long long int thisTask;
-
134  long long int partner;
-
135  long long int thisPattern;
-
136 
-
137  qreal realAv, imagAv;
-
138 
-
139 # ifdef _OPENMP
-
140 # pragma omp parallel \
-
141  default (none) \
-
142  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
-
143  private (thisTask,partner,thisPattern,realAv,imagAv)
-
144 # endif
-
145  {
-
146 # ifdef _OPENMP
-
147 # pragma omp for schedule (static)
-
148 # endif
-
149  for (thisTask=0; thisTask<numTasks; thisTask++){
-
150  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
151  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
152  // do dephase
-
153  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
154  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
155  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
156  } else {
-
157  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
158  // do depolarise
-
159  partner = thisTask | totMask;
-
160  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
161  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
162 
-
163  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
-
164  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
-
165 
-
166  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
-
167  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
-
168  }
-
169  }
-
170  }
-
171  }
-
172 }
-
173 
-
174 void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping) {
-
175  qreal retain=1-damping;
-
176  qreal dephase=sqrt(retain);
-
177 
-
178  long long int numTasks = qureg.numAmpsPerChunk;
-
179  long long int innerMask = 1LL << targetQubit;
-
180  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
181  long long int totMask = innerMask|outerMask;
-
182 
-
183  long long int thisTask;
-
184  long long int partner;
-
185  long long int thisPattern;
-
186 
-
187  //qreal realAv, imagAv;
-
188 
-
189 # ifdef _OPENMP
-
190 # pragma omp parallel \
-
191  default (none) \
-
192  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
-
193  private (thisTask,partner,thisPattern)
-
194 # endif
-
195  {
-
196 # ifdef _OPENMP
-
197 # pragma omp for schedule (static)
-
198 # endif
-
199  for (thisTask=0; thisTask<numTasks; thisTask++){
-
200  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
201  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
202  // do dephase
-
203  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
204  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
-
205  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
-
206  } else {
-
207  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
208  // do depolarise
-
209  partner = thisTask | totMask;
-
210  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
211  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
212 
-
213  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
-
214  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
-
215 
-
216  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
-
217  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
-
218  }
-
219  }
-
220  }
-
221  }
-
222 }
-
223 
-
224 void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel) {
-
225 
-
226  // first do dephase part.
-
227  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
-
228  // iterating over all elements in the state vector for the purpose of vectorisation
-
229  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
-
230  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
48 
+
49 
+
50 /*
+
51  * state vector and density matrix operations
+
52  */
+
53 
+
54 void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain){
+
55  long long int numTasks = qureg.numAmpsPerChunk;
+
56  long long int innerMask = 1LL << targetQubit;
+
57  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
58 
+
59  long long int thisTask;
+
60  long long int thisPattern;
+
61  long long int totMask = innerMask|outerMask;
+
62 
+
63 # ifdef _OPENMP
+
64 # pragma omp parallel \
+
65  default (none) \
+
66  shared (innerMask,outerMask,totMask,qureg,retain,numTasks, targetQubit) \
+
67  private (thisTask,thisPattern)
+
68 # endif
+
69  {
+
70 # ifdef _OPENMP
+
71 # pragma omp for schedule (static)
+
72 # endif
+
73  for (thisTask=0; thisTask<numTasks; thisTask++){
+
74  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
75  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
76  // do dephase
+
77  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
78  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
79  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
80  }
+
81  }
+
82  }
+
83 }
+
84 
+
85 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) {
+
86  qreal retain=1-dephase;
+
87  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
+
88 }
+
89 
+
90 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) {
+
91  qreal retain=1-dephase;
+
92 
+
93  long long int numTasks = qureg.numAmpsPerChunk;
+
94  long long int innerMaskQubit1 = 1LL << qubit1;
+
95  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
+
96  long long int innerMaskQubit2 = 1LL << qubit2;
+
97  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
+
98  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
+
99  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
+
100 
+
101  long long int thisTask;
+
102  long long int thisPatternQubit1, thisPatternQubit2;
+
103 
+
104 # ifdef _OPENMP
+
105 # pragma omp parallel \
+
106  default (none) \
+
107  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
+
108  totMaskQubit2,qureg,retain,numTasks) \
+
109  private (thisTask,thisPatternQubit1,thisPatternQubit2)
+
110 # endif
+
111  {
+
112 # ifdef _OPENMP
+
113 # pragma omp for schedule (static)
+
114 # endif
+
115  for (thisTask=0; thisTask<numTasks; thisTask++){
+
116  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
117  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
118 
+
119  // any mismatch |...0...><...1...| etc
+
120  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
+
121  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
+
122  // do dephase
+
123  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
124  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
125  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
126  }
+
127  }
+
128  }
+
129 }
+
130 
+
131 void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel) {
+
132  qreal retain=1-depolLevel;
+
133 
+
134  long long int numTasks = qureg.numAmpsPerChunk;
+
135  long long int innerMask = 1LL << targetQubit;
+
136  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
137  long long int totMask = innerMask|outerMask;
+
138 
+
139  long long int thisTask;
+
140  long long int partner;
+
141  long long int thisPattern;
+
142 
+
143  qreal realAv, imagAv;
+
144 
+
145 # ifdef _OPENMP
+
146 # pragma omp parallel \
+
147  default (none) \
+
148  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
+
149  private (thisTask,partner,thisPattern,realAv,imagAv)
+
150 # endif
+
151  {
+
152 # ifdef _OPENMP
+
153 # pragma omp for schedule (static)
+
154 # endif
+
155  for (thisTask=0; thisTask<numTasks; thisTask++){
+
156  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
157  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
158  // do dephase
+
159  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
160  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
161  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
162  } else {
+
163  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
+
164  // do depolarise
+
165  partner = thisTask | totMask;
+
166  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
+
167  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
+
168 
+
169  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
+
170  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
+
171 
+
172  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
+
173  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
+
174  }
+
175  }
+
176  }
+
177  }
+
178 }
+
179 
+
180 void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping) {
+
181  qreal retain=1-damping;
+
182  qreal dephase=sqrt(retain);
+
183 
+
184  long long int numTasks = qureg.numAmpsPerChunk;
+
185  long long int innerMask = 1LL << targetQubit;
+
186  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
187  long long int totMask = innerMask|outerMask;
+
188 
+
189  long long int thisTask;
+
190  long long int partner;
+
191  long long int thisPattern;
+
192 
+
193  //qreal realAv, imagAv;
+
194 
+
195 # ifdef _OPENMP
+
196 # pragma omp parallel \
+
197  default (none) \
+
198  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
+
199  private (thisTask,partner,thisPattern)
+
200 # endif
+
201  {
+
202 # ifdef _OPENMP
+
203 # pragma omp for schedule (static)
+
204 # endif
+
205  for (thisTask=0; thisTask<numTasks; thisTask++){
+
206  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
207  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
208  // do dephase
+
209  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
210  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
+
211  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
+
212  } else {
+
213  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
+
214  // do depolarise
+
215  partner = thisTask | totMask;
+
216  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
+
217  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
+
218 
+
219  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
+
220  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
+
221 
+
222  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
+
223  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
+
224  }
+
225  }
+
226  }
+
227  }
+
228 }
+
229 
+
230 void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel) {
231 
-
232  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
233  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
234  long long int thisInnerBlock, // current block
-
235  thisOuterColumn, // current column in density matrix
-
236  thisIndex, // current index in (density matrix representation) state vector
-
237  thisIndexInOuterColumn,
-
238  thisIndexInInnerBlock;
-
239  int outerBit;
-
240 
-
241  long long int thisTask;
-
242  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
243 
-
244  // set dimensions
-
245  sizeInnerHalfBlock = 1LL << targetQubit;
-
246  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
247  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
248  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
232  // first do dephase part.
+
233  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
+
234  // iterating over all elements in the state vector for the purpose of vectorisation
+
235  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
+
236  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
237 
+
238  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
239  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
240  long long int thisInnerBlock, // current block
+
241  thisOuterColumn, // current column in density matrix
+
242  thisIndex, // current index in (density matrix representation) state vector
+
243  thisIndexInOuterColumn,
+
244  thisIndexInInnerBlock;
+
245  int outerBit;
+
246 
+
247  long long int thisTask;
+
248  long long int numTasks=qureg.numAmpsPerChunk>>1;
249 
-
250 # ifdef _OPENMP
-
251 # pragma omp parallel \
-
252  default (none) \
-
253  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
254  qureg,depolLevel,numTasks,targetQubit) \
-
255  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
256  thisIndexInInnerBlock,outerBit)
-
257 # endif
-
258  {
-
259 # ifdef _OPENMP
-
260 # pragma omp for schedule (static)
-
261 # endif
-
262  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
263  // treat this as iterating over all columns, then iterating over half the values
-
264  // within one column.
-
265  // If this function has been called, this process' chunk contains half an
-
266  // outer block or less
-
267  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
268  // we want to process all columns in the density matrix,
-
269  // updating the values for half of each column (one half of each inner block)
-
270  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
271  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
272  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
273  // get index in state vector corresponding to upper inner block
-
274  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
275  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
276  + thisIndexInInnerBlock;
-
277  // check if we are in the upper or lower half of an outer block
-
278  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
279  // if we are in the lower half of an outer block, shift to be in the lower half
-
280  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
281  thisIndex += outerBit*(sizeInnerHalfBlock);
-
282 
-
283  // NOTE: at this point thisIndex should be the index of the element we want to
-
284  // dephase in the chunk of the state vector on this process, in the
-
285  // density matrix representation.
-
286  // thisTask is the index of the pair element in pairStateVec
-
287 
-
288 
-
289  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
290  // + pair[thisTask])/2
-
291  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
-
292  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
-
293 
-
294  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
-
295  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
-
296  }
-
297  }
-
298 }
-
299 
-
300 void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping) {
-
301  qreal retain=1-damping;
-
302  qreal dephase=sqrt(1-damping);
-
303 
-
304  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
-
305  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
306 
-
307  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
-
308 
-
309  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
310  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
311  long long int thisInnerBlock, // current block
-
312  thisOuterColumn, // current column in density matrix
-
313  thisIndex, // current index in (density matrix representation) state vector
-
314  thisIndexInOuterColumn,
-
315  thisIndexInInnerBlock;
-
316  int outerBit;
-
317  int stateBit;
-
318 
-
319  long long int thisTask;
-
320  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
321 
-
322  // set dimensions
-
323  sizeInnerHalfBlock = 1LL << targetQubit;
-
324  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
325  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
326  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
250  // set dimensions
+
251  sizeInnerHalfBlock = 1LL << targetQubit;
+
252  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
253  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
254  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
255 
+
256 # ifdef _OPENMP
+
257 # pragma omp parallel \
+
258  default (none) \
+
259  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
260  qureg,depolLevel,numTasks,targetQubit) \
+
261  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
262  thisIndexInInnerBlock,outerBit)
+
263 # endif
+
264  {
+
265 # ifdef _OPENMP
+
266 # pragma omp for schedule (static)
+
267 # endif
+
268  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
269  // treat this as iterating over all columns, then iterating over half the values
+
270  // within one column.
+
271  // If this function has been called, this process' chunk contains half an
+
272  // outer block or less
+
273  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
274  // we want to process all columns in the density matrix,
+
275  // updating the values for half of each column (one half of each inner block)
+
276  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
277  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
278  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
279  // get index in state vector corresponding to upper inner block
+
280  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
281  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
282  + thisIndexInInnerBlock;
+
283  // check if we are in the upper or lower half of an outer block
+
284  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
285  // if we are in the lower half of an outer block, shift to be in the lower half
+
286  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
287  thisIndex += outerBit*(sizeInnerHalfBlock);
+
288 
+
289  // NOTE: at this point thisIndex should be the index of the element we want to
+
290  // dephase in the chunk of the state vector on this process, in the
+
291  // density matrix representation.
+
292  // thisTask is the index of the pair element in pairStateVec
+
293 
+
294 
+
295  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
296  // + pair[thisTask])/2
+
297  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
+
298  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
+
299 
+
300  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
+
301  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
+
302  }
+
303  }
+
304 }
+
305 
+
306 void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping) {
+
307  qreal retain=1-damping;
+
308  qreal dephase=sqrt(1-damping);
+
309 
+
310  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
+
311  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
+
312 
+
313  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
+
314 
+
315  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
316  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
317  long long int thisInnerBlock, // current block
+
318  thisOuterColumn, // current column in density matrix
+
319  thisIndex, // current index in (density matrix representation) state vector
+
320  thisIndexInOuterColumn,
+
321  thisIndexInInnerBlock;
+
322  int outerBit;
+
323  int stateBit;
+
324 
+
325  long long int thisTask;
+
326  long long int numTasks=qureg.numAmpsPerChunk>>1;
327 
-
328 # ifdef _OPENMP
-
329 # pragma omp parallel \
-
330  default (none) \
-
331  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
332  qureg,damping, retain, dephase, numTasks,targetQubit) \
-
333  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
334  thisIndexInInnerBlock,outerBit, stateBit)
-
335 # endif
-
336  {
-
337 # ifdef _OPENMP
-
338 # pragma omp for schedule (static)
-
339 # endif
-
340  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
341  // treat this as iterating over all columns, then iterating over half the values
-
342  // within one column.
-
343  // If this function has been called, this process' chunk contains half an
-
344  // outer block or less
-
345  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
346  // we want to process all columns in the density matrix,
-
347  // updating the values for half of each column (one half of each inner block)
-
348  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
349  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
350  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
351  // get index in state vector corresponding to upper inner block
-
352  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
353  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
354  + thisIndexInInnerBlock;
-
355  // check if we are in the upper or lower half of an outer block
-
356  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
357  // if we are in the lower half of an outer block, shift to be in the lower half
-
358  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
359  thisIndex += outerBit*(sizeInnerHalfBlock);
-
360 
-
361  // NOTE: at this point thisIndex should be the index of the element we want to
-
362  // dephase in the chunk of the state vector on this process, in the
-
363  // density matrix representation.
-
364  // thisTask is the index of the pair element in pairStateVec
-
365 
-
366  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
-
367  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
-
368  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
-
369 
-
370  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
371  // + pair[thisTask])/2
-
372  if(stateBit == 0){
-
373  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
-
374  damping*( qureg.pairStateVec.real[thisTask]);
-
375 
-
376  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
-
377  damping*( qureg.pairStateVec.imag[thisTask]);
-
378  } else{
-
379  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
-
380 
-
381  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
-
382  }
-
383  }
-
384  }
-
385 }
-
386 
-
387 void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma) {
-
388  long long int numTasks = qureg.numAmpsPerChunk;
-
389  long long int innerMaskQubit1 = 1LL << qubit1;
-
390  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
391  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
392  long long int innerMaskQubit2 = 1LL << qubit2;
-
393  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
394  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
395 
-
396  long long int thisTask;
-
397  long long int partner;
-
398  long long int thisPatternQubit1, thisPatternQubit2;
-
399 
-
400  qreal real00, imag00;
+
328  // set dimensions
+
329  sizeInnerHalfBlock = 1LL << targetQubit;
+
330  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
331  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
332  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
333 
+
334 # ifdef _OPENMP
+
335 # pragma omp parallel \
+
336  default (none) \
+
337  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
338  qureg,damping, retain, dephase, numTasks,targetQubit) \
+
339  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
340  thisIndexInInnerBlock,outerBit, stateBit)
+
341 # endif
+
342  {
+
343 # ifdef _OPENMP
+
344 # pragma omp for schedule (static)
+
345 # endif
+
346  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
347  // treat this as iterating over all columns, then iterating over half the values
+
348  // within one column.
+
349  // If this function has been called, this process' chunk contains half an
+
350  // outer block or less
+
351  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
352  // we want to process all columns in the density matrix,
+
353  // updating the values for half of each column (one half of each inner block)
+
354  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
355  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
356  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
357  // get index in state vector corresponding to upper inner block
+
358  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
359  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
360  + thisIndexInInnerBlock;
+
361  // check if we are in the upper or lower half of an outer block
+
362  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
363  // if we are in the lower half of an outer block, shift to be in the lower half
+
364  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
365  thisIndex += outerBit*(sizeInnerHalfBlock);
+
366 
+
367  // NOTE: at this point thisIndex should be the index of the element we want to
+
368  // dephase in the chunk of the state vector on this process, in the
+
369  // density matrix representation.
+
370  // thisTask is the index of the pair element in pairStateVec
+
371 
+
372  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
+
373  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
+
374  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
+
375 
+
376  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
377  // + pair[thisTask])/2
+
378  if(stateBit == 0){
+
379  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
+
380  damping*( qureg.pairStateVec.real[thisTask]);
+
381 
+
382  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
+
383  damping*( qureg.pairStateVec.imag[thisTask]);
+
384  } else{
+
385  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
+
386 
+
387  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
+
388  }
+
389  }
+
390  }
+
391 }
+
392 
+
393 void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma) {
+
394  long long int numTasks = qureg.numAmpsPerChunk;
+
395  long long int innerMaskQubit1 = 1LL << qubit1;
+
396  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
+
397  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
+
398  long long int innerMaskQubit2 = 1LL << qubit2;
+
399  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
+
400  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
401 
-
402 # ifdef _OPENMP
-
403 # pragma omp parallel \
-
404  default (none) \
-
405  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
-
406  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
407 # endif
-
408  {
-
409 # ifdef _OPENMP
-
410 # pragma omp for schedule (static)
-
411 # endif
-
412  //--------------------------------------- STEP ONE ---------------------
-
413  for (thisTask=0; thisTask<numTasks; thisTask++){
-
414  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
415  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
416  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
417  || (thisPatternQubit2==totMaskQubit2))){
-
418  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
419  partner = thisTask | totMaskQubit1;
-
420  real00 = qureg.stateVec.real[thisTask];
-
421  imag00 = qureg.stateVec.imag[thisTask];
-
422 
-
423  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
424  + delta*qureg.stateVec.real[partner];
-
425  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
426  + delta*qureg.stateVec.imag[partner];
-
427 
-
428  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
429  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
430 
-
431  }
-
432  }
-
433 # ifdef _OPENMP
-
434 # pragma omp for schedule (static)
-
435 # endif
-
436  //--------------------------------------- STEP TWO ---------------------
-
437  for (thisTask=0; thisTask<numTasks; thisTask++){
-
438  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
439  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
440  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
441  || (thisPatternQubit1==totMaskQubit1))){
-
442  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
443  partner = thisTask | totMaskQubit2;
-
444  real00 = qureg.stateVec.real[thisTask];
-
445  imag00 = qureg.stateVec.imag[thisTask];
-
446 
-
447  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
448  + delta*qureg.stateVec.real[partner];
-
449  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
450  + delta*qureg.stateVec.imag[partner];
-
451 
-
452  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
453  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
454 
-
455  }
-
456  }
-
457 
-
458 # ifdef _OPENMP
-
459 # pragma omp for schedule (static)
-
460 # endif
-
461  //--------------------------------------- STEP THREE ---------------------
-
462  for (thisTask=0; thisTask<numTasks; thisTask++){
-
463  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
464  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
465  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
466  || (thisPatternQubit1==totMaskQubit1))){
-
467  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
468  partner = thisTask | totMaskQubit2;
-
469  partner = partner ^ totMaskQubit1;
-
470  real00 = qureg.stateVec.real[thisTask];
-
471  imag00 = qureg.stateVec.imag[thisTask];
-
472 
-
473  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
-
474  + delta*qureg.stateVec.real[partner]);
-
475  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
-
476  + delta*qureg.stateVec.imag[partner]);
-
477 
-
478  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
-
479  + delta*real00);
-
480  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
-
481  + delta*imag00);
-
482 
-
483  }
-
484  }
-
485  }
-
486 }
-
487 
-
488 void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta) {
-
489  long long int numTasks = qureg.numAmpsPerChunk;
-
490  long long int innerMaskQubit1 = 1LL << qubit1;
-
491  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
492  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
493  long long int innerMaskQubit2 = 1LL << qubit2;
-
494  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
495  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
496  // correct for being in a particular chunk
-
497  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
-
498 
-
499 
-
500  long long int thisTask;
-
501  long long int partner;
-
502  long long int thisPatternQubit1, thisPatternQubit2;
-
503 
-
504  qreal real00, imag00;
+
402  long long int thisTask;
+
403  long long int partner;
+
404  long long int thisPatternQubit1, thisPatternQubit2;
+
405 
+
406  qreal real00, imag00;
+
407 
+
408 # ifdef _OPENMP
+
409 # pragma omp parallel \
+
410  default (none) \
+
411  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
+
412  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
+
413 # endif
+
414  {
+
415 # ifdef _OPENMP
+
416 # pragma omp for schedule (static)
+
417 # endif
+
418  //--------------------------------------- STEP ONE ---------------------
+
419  for (thisTask=0; thisTask<numTasks; thisTask++){
+
420  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
421  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
422  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
+
423  || (thisPatternQubit2==totMaskQubit2))){
+
424  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
+
425  partner = thisTask | totMaskQubit1;
+
426  real00 = qureg.stateVec.real[thisTask];
+
427  imag00 = qureg.stateVec.imag[thisTask];
+
428 
+
429  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
430  + delta*qureg.stateVec.real[partner];
+
431  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
432  + delta*qureg.stateVec.imag[partner];
+
433 
+
434  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
435  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
436 
+
437  }
+
438  }
+
439 # ifdef _OPENMP
+
440 # pragma omp for schedule (static)
+
441 # endif
+
442  //--------------------------------------- STEP TWO ---------------------
+
443  for (thisTask=0; thisTask<numTasks; thisTask++){
+
444  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
445  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
446  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
+
447  || (thisPatternQubit1==totMaskQubit1))){
+
448  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
+
449  partner = thisTask | totMaskQubit2;
+
450  real00 = qureg.stateVec.real[thisTask];
+
451  imag00 = qureg.stateVec.imag[thisTask];
+
452 
+
453  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
454  + delta*qureg.stateVec.real[partner];
+
455  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
456  + delta*qureg.stateVec.imag[partner];
+
457 
+
458  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
459  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
460 
+
461  }
+
462  }
+
463 
+
464 # ifdef _OPENMP
+
465 # pragma omp for schedule (static)
+
466 # endif
+
467  //--------------------------------------- STEP THREE ---------------------
+
468  for (thisTask=0; thisTask<numTasks; thisTask++){
+
469  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
470  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
471  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
+
472  || (thisPatternQubit1==totMaskQubit1))){
+
473  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
+
474  partner = thisTask | totMaskQubit2;
+
475  partner = partner ^ totMaskQubit1;
+
476  real00 = qureg.stateVec.real[thisTask];
+
477  imag00 = qureg.stateVec.imag[thisTask];
+
478 
+
479  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
+
480  + delta*qureg.stateVec.real[partner]);
+
481  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
+
482  + delta*qureg.stateVec.imag[partner]);
+
483 
+
484  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
+
485  + delta*real00);
+
486  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
+
487  + delta*imag00);
+
488 
+
489  }
+
490  }
+
491  }
+
492 }
+
493 
+
494 void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta) {
+
495  long long int numTasks = qureg.numAmpsPerChunk;
+
496  long long int innerMaskQubit1 = 1LL << qubit1;
+
497  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
+
498  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
+
499  long long int innerMaskQubit2 = 1LL << qubit2;
+
500  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
+
501  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
+
502  // correct for being in a particular chunk
+
503  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
+
504 
505 
-
506 # ifdef _OPENMP
-
507 # pragma omp parallel \
-
508  default (none) \
-
509  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
-
510  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
511 # endif
-
512  {
-
513 
-
514 # ifdef _OPENMP
-
515 # pragma omp for schedule (static)
-
516 # endif
-
517  //--------------------------------------- STEP ONE ---------------------
-
518  for (thisTask=0; thisTask<numTasks; thisTask ++){
-
519  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
520  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
521  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
522  || (thisPatternQubit2==totMaskQubit2))){
-
523  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
524  partner = thisTask | totMaskQubit1;
-
525  real00 = qureg.stateVec.real[thisTask];
-
526  imag00 = qureg.stateVec.imag[thisTask];
-
527 
-
528  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
529  + delta*qureg.stateVec.real[partner];
-
530  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
531  + delta*qureg.stateVec.imag[partner];
-
532 
-
533  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
534  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
535 
-
536  }
-
537  }
-
538  }
-
539 }
-
540 
- -
542  int qubit2, qreal delta, qreal gamma) {
-
543 
-
544  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
545  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
546  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
547  long long int thisInnerBlockQ2,
-
548  thisOuterColumn, // current column in density matrix
-
549  thisIndex, // current index in (density matrix representation) state vector
-
550  thisIndexInOuterColumn,
-
551  thisIndexInInnerBlockQ1,
-
552  thisIndexInInnerBlockQ2,
-
553  thisInnerBlockQ1InInnerBlockQ2;
-
554  int outerBitQ1, outerBitQ2;
-
555 
-
556  long long int thisTask;
-
557  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
558 
-
559  // set dimensions
-
560  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
561  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
562  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
563  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
564  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
565  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
566  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
567 
-
568 # ifdef _OPENMP
-
569 # pragma omp parallel \
-
570  default (none) \
-
571  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
572  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
-
573  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
574  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
575  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
576 # endif
-
577  {
-
578 # ifdef _OPENMP
-
579 # pragma omp for schedule (static)
-
580 # endif
-
581  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
582  // treat this as iterating over all columns, then iterating over half the values
-
583  // within one column.
-
584  // If this function has been called, this process' chunk contains half an
-
585  // outer block or less
-
586  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
587  // we want to process all columns in the density matrix,
-
588  // updating the values for half of each column (one half of each inner block)
-
589  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
590  // thisTask % sizeOuterQuarterColumn
-
591  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
592  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
593  // thisTask % sizeInnerQuarterBlockQ2;
-
594  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
595  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
596  // thisTask % sizeInnerHalfBlockQ1;
-
597  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
598 
-
599  // get index in state vector corresponding to upper inner block
-
600  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
601  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
602 
-
603  // check if we are in the upper or lower half of an outer block for Q1
-
604  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
605  // if we are in the lower half of an outer block, shift to be in the lower half
-
606  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
607  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+
506  long long int thisTask;
+
507  long long int partner;
+
508  long long int thisPatternQubit1, thisPatternQubit2;
+
509 
+
510  qreal real00, imag00;
+
511 
+
512 # ifdef _OPENMP
+
513 # pragma omp parallel \
+
514  default (none) \
+
515  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
+
516  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
+
517 # endif
+
518  {
+
519 
+
520 # ifdef _OPENMP
+
521 # pragma omp for schedule (static)
+
522 # endif
+
523  //--------------------------------------- STEP ONE ---------------------
+
524  for (thisTask=0; thisTask<numTasks; thisTask ++){
+
525  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
526  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
527  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
+
528  || (thisPatternQubit2==totMaskQubit2))){
+
529  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
+
530  partner = thisTask | totMaskQubit1;
+
531  real00 = qureg.stateVec.real[thisTask];
+
532  imag00 = qureg.stateVec.imag[thisTask];
+
533 
+
534  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
535  + delta*qureg.stateVec.real[partner];
+
536  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
537  + delta*qureg.stateVec.imag[partner];
+
538 
+
539  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
540  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
541 
+
542  }
+
543  }
+
544  }
+
545 }
+
546 
+ +
548  int qubit2, qreal delta, qreal gamma) {
+
549 
+
550  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
551  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
552  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
553  long long int thisInnerBlockQ2,
+
554  thisOuterColumn, // current column in density matrix
+
555  thisIndex, // current index in (density matrix representation) state vector
+
556  thisIndexInOuterColumn,
+
557  thisIndexInInnerBlockQ1,
+
558  thisIndexInInnerBlockQ2,
+
559  thisInnerBlockQ1InInnerBlockQ2;
+
560  int outerBitQ1, outerBitQ2;
+
561 
+
562  long long int thisTask;
+
563  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
564 
+
565  // set dimensions
+
566  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
567  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
568  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
569  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
570  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
571  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
572  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
573 
+
574 # ifdef _OPENMP
+
575 # pragma omp parallel \
+
576  default (none) \
+
577  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
+
578  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
+
579  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
+
580  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
581  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
+
582 # endif
+
583  {
+
584 # ifdef _OPENMP
+
585 # pragma omp for schedule (static)
+
586 # endif
+
587  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
588  // treat this as iterating over all columns, then iterating over half the values
+
589  // within one column.
+
590  // If this function has been called, this process' chunk contains half an
+
591  // outer block or less
+
592  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
593  // we want to process all columns in the density matrix,
+
594  // updating the values for half of each column (one half of each inner block)
+
595  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
596  // thisTask % sizeOuterQuarterColumn
+
597  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
598  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
599  // thisTask % sizeInnerQuarterBlockQ2;
+
600  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
601  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
602  // thisTask % sizeInnerHalfBlockQ1;
+
603  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
+
604 
+
605  // get index in state vector corresponding to upper inner block
+
606  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
607  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
608 
-
609  // check if we are in the upper or lower half of an outer block for Q2
-
610  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
609  // check if we are in the upper or lower half of an outer block for Q1
+
610  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
611  // if we are in the lower half of an outer block, shift to be in the lower half
612  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
613  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
613  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
614 
-
615  // NOTE: at this point thisIndex should be the index of the element we want to
-
616  // dephase in the chunk of the state vector on this process, in the
-
617  // density matrix representation.
-
618  // thisTask is the index of the pair element in pairStateVec
-
619 
-
620 
-
621  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
622  // + pair[thisTask])/2
-
623  // NOTE: must set gamma=1 if using this function for steps 1 or 2
-
624  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
625  delta*qureg.pairStateVec.real[thisTask]);
-
626  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
627  delta*qureg.pairStateVec.imag[thisTask]);
-
628  }
-
629  }
-
630 }
-
631 
- -
633  int qubit2, qreal delta, qreal gamma) {
-
634 
-
635  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
636  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
637  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
638  long long int thisInnerBlockQ2,
-
639  thisOuterColumn, // current column in density matrix
-
640  thisIndex, // current index in (density matrix representation) state vector
-
641  thisIndexInPairVector,
-
642  thisIndexInOuterColumn,
-
643  thisIndexInInnerBlockQ1,
-
644  thisIndexInInnerBlockQ2,
-
645  thisInnerBlockQ1InInnerBlockQ2;
-
646  int outerBitQ1, outerBitQ2;
-
647 
-
648  long long int thisTask;
-
649  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
650 
-
651  // set dimensions
-
652  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
653  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
654  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
655  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
656  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
657  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
658  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
659 
-
660 //# if 0
-
661 # ifdef _OPENMP
-
662 # pragma omp parallel \
-
663  default (none) \
-
664  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
665  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
-
666  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
667  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
-
668  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
669 # endif
-
670  {
-
671 # ifdef _OPENMP
-
672 # pragma omp for schedule (static)
-
673 # endif
-
674 //# endif
-
675  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
676  // treat this as iterating over all columns, then iterating over half the values
-
677  // within one column.
-
678  // If this function has been called, this process' chunk contains half an
-
679  // outer block or less
-
680  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
681  // we want to process all columns in the density matrix,
-
682  // updating the values for half of each column (one half of each inner block)
-
683  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
684  // thisTask % sizeOuterQuarterColumn
-
685  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
686  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
687  // thisTask % sizeInnerQuarterBlockQ2;
-
688  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
689  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
690  // thisTask % sizeInnerHalfBlockQ1;
-
691  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
692 
-
693  // get index in state vector corresponding to upper inner block
-
694  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
695  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
696 
-
697  // check if we are in the upper or lower half of an outer block for Q1
-
698  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
699  // if we are in the lower half of an outer block, shift to be in the lower half
-
700  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
701  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
702 
-
703  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
-
704  // Find correct index in pairStateVector
-
705  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
-
706  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
-
707 
-
708  // check if we are in the upper or lower half of an outer block for Q2
-
709  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
710  // if we are in the lower half of an outer block, shift to be in the lower half
-
711  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
712  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
615  // check if we are in the upper or lower half of an outer block for Q2
+
616  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
617  // if we are in the lower half of an outer block, shift to be in the lower half
+
618  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
619  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
620 
+
621  // NOTE: at this point thisIndex should be the index of the element we want to
+
622  // dephase in the chunk of the state vector on this process, in the
+
623  // density matrix representation.
+
624  // thisTask is the index of the pair element in pairStateVec
+
625 
+
626 
+
627  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
628  // + pair[thisTask])/2
+
629  // NOTE: must set gamma=1 if using this function for steps 1 or 2
+
630  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
+
631  delta*qureg.pairStateVec.real[thisTask]);
+
632  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
+
633  delta*qureg.pairStateVec.imag[thisTask]);
+
634  }
+
635  }
+
636 }
+
637 
+ +
639  int qubit2, qreal delta, qreal gamma) {
+
640 
+
641  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
642  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
643  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
644  long long int thisInnerBlockQ2,
+
645  thisOuterColumn, // current column in density matrix
+
646  thisIndex, // current index in (density matrix representation) state vector
+
647  thisIndexInPairVector,
+
648  thisIndexInOuterColumn,
+
649  thisIndexInInnerBlockQ1,
+
650  thisIndexInInnerBlockQ2,
+
651  thisInnerBlockQ1InInnerBlockQ2;
+
652  int outerBitQ1, outerBitQ2;
+
653 
+
654  long long int thisTask;
+
655  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
656 
+
657  // set dimensions
+
658  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
659  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
660  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
661  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
662  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
663  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
664  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
665 
+
666 //# if 0
+
667 # ifdef _OPENMP
+
668 # pragma omp parallel \
+
669  default (none) \
+
670  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
+
671  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
+
672  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
+
673  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
+
674  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
+
675 # endif
+
676  {
+
677 # ifdef _OPENMP
+
678 # pragma omp for schedule (static)
+
679 # endif
+
680 //# endif
+
681  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
682  // treat this as iterating over all columns, then iterating over half the values
+
683  // within one column.
+
684  // If this function has been called, this process' chunk contains half an
+
685  // outer block or less
+
686  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
687  // we want to process all columns in the density matrix,
+
688  // updating the values for half of each column (one half of each inner block)
+
689  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
690  // thisTask % sizeOuterQuarterColumn
+
691  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
692  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
693  // thisTask % sizeInnerQuarterBlockQ2;
+
694  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
695  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
696  // thisTask % sizeInnerHalfBlockQ1;
+
697  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
+
698 
+
699  // get index in state vector corresponding to upper inner block
+
700  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
701  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
702 
+
703  // check if we are in the upper or lower half of an outer block for Q1
+
704  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
705  // if we are in the lower half of an outer block, shift to be in the lower half
+
706  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
707  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+
708 
+
709  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
+
710  // Find correct index in pairStateVector
+
711  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
+
712  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
713 
-
714 
-
715  // NOTE: at this point thisIndex should be the index of the element we want to
-
716  // dephase in the chunk of the state vector on this process, in the
-
717  // density matrix representation.
-
718 
-
719 
-
720  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
721  // + pair[thisIndexInPairVector])/2
-
722  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
723  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
-
724 
-
725  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
726  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
-
727  }
-
728  }
-
729 
-
730 }
-
731 
-
732 
-
733 /* Without nested parallelisation, only the outer most loops which call below are parallelised */
-
734 void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps) {
-
735  long long int i;
-
736 # ifdef _OPENMP
-
737 # pragma omp parallel for schedule (static)
-
738 # endif
-
739  for (i=startInd; i < startInd+numAmps; i++) {
-
740  qureg.stateVec.real[i] = 0;
-
741  qureg.stateVec.imag[i] = 0;
-
742  }
-
743 }
-
744 void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps) {
-
745  long long int i;
-
746 # ifdef _OPENMP
-
747 # pragma omp parallel for schedule (static)
-
748 # endif
-
749  for (i=startInd; i < startInd+numAmps; i++) {
-
750  qureg.stateVec.real[i] /= norm;
-
751  qureg.stateVec.imag[i] /= norm;
-
752  }
-
753 }
- -
755  Qureg qureg, qreal norm, int normFirst,
-
756  long long int startAmpInd, long long int numAmps, long long int blockSize
-
757 ) {
-
758  long long int numDubBlocks = numAmps / (2*blockSize);
-
759  long long int blockStartInd;
-
760 
-
761  if (normFirst) {
-
762  long long int dubBlockInd;
-
763 # ifdef _OPENMP
-
764 # pragma omp parallel for schedule (static) private (blockStartInd)
-
765 # endif
-
766  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
767  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
768  normaliseSomeAmps(qureg, norm, blockStartInd, blockSize); // |0><0|
-
769  zeroSomeAmps( qureg, blockStartInd + blockSize, blockSize);
-
770  }
-
771  } else {
-
772  long long int dubBlockInd;
-
773 # ifdef _OPENMP
-
774 # pragma omp parallel for schedule (static) private (blockStartInd)
-
775 # endif
-
776  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
-
777  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
-
778  zeroSomeAmps( qureg, blockStartInd, blockSize);
-
779  normaliseSomeAmps(qureg, norm, blockStartInd + blockSize, blockSize); // |1><1|
-
780  }
-
781  }
-
782 }
-
783 
-
785 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb) {
-
786 
-
787  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
-
788  // where n = measureQubit, q = qureg.numQubitsRepresented.
-
789  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
-
790  // stepping in sub-blocks of 2^q, killing every second.
-
791  // When outcome=1, we offset the start of these blocks by their size.
-
792  long long int innerBlockSize = (1LL << measureQubit);
-
793  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
-
794 
-
795  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
-
796  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
-
797  long long int locNumAmps = qureg.numAmpsPerChunk;
-
798  long long int globalStartInd = qureg.chunkId * locNumAmps;
-
799  int innerBit = extractBit(measureQubit, globalStartInd);
-
800  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
-
801 
-
802  // If this chunk's amps are entirely inside an outer block
-
803  if (locNumAmps <= outerBlockSize) {
-
804 
-
805  // if this is an undesired outer block, kill all elems
-
806  if (outerBit != outcome)
-
807  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
808 
-
809  // othwerwise, if this is a desired outer block, and also entirely an inner block
-
810  if (locNumAmps <= innerBlockSize) {
-
811 
-
812  // and that inner block is undesired, kill all elems
-
813  if (innerBit != outcome)
-
814  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
815  // otherwise normalise all elems
-
816  else
-
817  return normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
-
818  }
-
819 
-
820  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
- -
822  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
-
823  }
-
824 
-
825  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
-
826  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
-
827  long long int firstBlockInd;
-
828 
-
829  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
-
830  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
-
831  // inner parallelisation
-
832  if (outerBit == outcome) {
-
833 
-
834  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
835  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
836 
-
837  // *norm only the desired inner blocks in the desired outer block
- -
839  qureg, totalStateProb, innerBit==outcome,
-
840  firstBlockInd, outerBlockSize, innerBlockSize);
-
841 
-
842  // zero the undesired outer block
-
843  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
-
844  }
-
845 
-
846  } else {
-
847 
-
848  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
849  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
850 
-
851  // same thing but undesired outer blocks come first
-
852  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
- -
854  qureg, totalStateProb, innerBit==outcome,
-
855  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
-
856  }
-
857  }
-
858 
-
859 }
-
860 
- -
862 
-
863  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
-
864  long long int index;
-
865  long long int numAmps = qureg.numAmpsPerChunk;
-
866 
-
867  qreal trace = 0;
-
868  qreal *vecRe = qureg.stateVec.real;
-
869  qreal *vecIm = qureg.stateVec.imag;
-
870 
-
871 # ifdef _OPENMP
-
872 # pragma omp parallel \
-
873  shared (vecRe, vecIm, numAmps) \
-
874  private (index) \
-
875  reduction ( +:trace )
-
876 # endif
-
877  {
-
878 # ifdef _OPENMP
-
879 # pragma omp for schedule (static)
-
880 # endif
-
881  for (index=0LL; index<numAmps; index++) {
-
882 
-
883  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
-
884  }
-
885  }
-
886 
-
887  return trace;
-
888 }
-
889 
-
890 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
-
891 
-
892  /* corresponding amplitudes live on the same node (same dimensions) */
-
893 
-
894  // unpack vars for OpenMP
-
895  qreal* combineVecRe = combineQureg.stateVec.real;
-
896  qreal* combineVecIm = combineQureg.stateVec.imag;
-
897  qreal* otherVecRe = otherQureg.stateVec.real;
-
898  qreal* otherVecIm = otherQureg.stateVec.imag;
-
899  long long int numAmps = combineQureg.numAmpsPerChunk;
-
900  long long int index;
-
901 
-
902 # ifdef _OPENMP
-
903 # pragma omp parallel \
-
904  default (none) \
-
905  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
-
906  private (index)
-
907 # endif
-
908  {
-
909 # ifdef _OPENMP
-
910 # pragma omp for schedule (static)
-
911 # endif
-
912  for (index=0; index < numAmps; index++) {
-
913  combineVecRe[index] *= 1-otherProb;
-
914  combineVecIm[index] *= 1-otherProb;
-
915 
-
916  combineVecRe[index] += otherProb * otherVecRe[index];
-
917  combineVecIm[index] += otherProb * otherVecIm[index];
-
918  }
-
919  }
-
920 }
-
921 
- -
924 
-
925  long long int index;
-
926  long long int numAmps = a.numAmpsPerChunk;
-
927 
-
928  qreal *aRe = a.stateVec.real;
-
929  qreal *aIm = a.stateVec.imag;
-
930  qreal *bRe = b.stateVec.real;
-
931  qreal *bIm = b.stateVec.imag;
-
932 
-
933  qreal trace = 0;
-
934  qreal difRe, difIm;
+
714  // check if we are in the upper or lower half of an outer block for Q2
+
715  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
716  // if we are in the lower half of an outer block, shift to be in the lower half
+
717  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
718  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
719 
+
720 
+
721  // NOTE: at this point thisIndex should be the index of the element we want to
+
722  // dephase in the chunk of the state vector on this process, in the
+
723  // density matrix representation.
+
724 
+
725 
+
726  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
727  // + pair[thisIndexInPairVector])/2
+
728  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
+
729  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
+
730 
+
731  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
+
732  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
+
733  }
+
734  }
+
735 
+
736 }
+
737 
+
738 
+
739 /* Without nested parallelisation, only the outer most loops which call below are parallelised */
+
740 void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps) {
+
741  long long int i;
+
742 # ifdef _OPENMP
+
743 # pragma omp parallel for schedule (static)
+
744 # endif
+
745  for (i=startInd; i < startInd+numAmps; i++) {
+
746  qureg.stateVec.real[i] = 0;
+
747  qureg.stateVec.imag[i] = 0;
+
748  }
+
749 }
+
750 void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps) {
+
751  long long int i;
+
752 # ifdef _OPENMP
+
753 # pragma omp parallel for schedule (static)
+
754 # endif
+
755  for (i=startInd; i < startInd+numAmps; i++) {
+
756  qureg.stateVec.real[i] /= norm;
+
757  qureg.stateVec.imag[i] /= norm;
+
758  }
+
759 }
+ +
761  Qureg qureg, qreal norm, int normFirst,
+
762  long long int startAmpInd, long long int numAmps, long long int blockSize
+
763 ) {
+
764  long long int numDubBlocks = numAmps / (2*blockSize);
+
765  long long int blockStartInd;
+
766 
+
767  if (normFirst) {
+
768  long long int dubBlockInd;
+
769 # ifdef _OPENMP
+
770 # pragma omp parallel for schedule (static) private (blockStartInd)
+
771 # endif
+
772  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
+
773  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
+
774  normaliseSomeAmps(qureg, norm, blockStartInd, blockSize); // |0><0|
+
775  zeroSomeAmps( qureg, blockStartInd + blockSize, blockSize);
+
776  }
+
777  } else {
+
778  long long int dubBlockInd;
+
779 # ifdef _OPENMP
+
780 # pragma omp parallel for schedule (static) private (blockStartInd)
+
781 # endif
+
782  for (dubBlockInd=0; dubBlockInd < numDubBlocks; dubBlockInd++) {
+
783  blockStartInd = startAmpInd + dubBlockInd*2*blockSize;
+
784  zeroSomeAmps( qureg, blockStartInd, blockSize);
+
785  normaliseSomeAmps(qureg, norm, blockStartInd + blockSize, blockSize); // |1><1|
+
786  }
+
787  }
+
788 }
+
789 
+
791 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb) {
+
792 
+
793  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
+
794  // where n = measureQubit, q = qureg.numQubitsRepresented.
+
795  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
+
796  // stepping in sub-blocks of 2^q, killing every second.
+
797  // When outcome=1, we offset the start of these blocks by their size.
+
798  long long int innerBlockSize = (1LL << measureQubit);
+
799  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
+
800 
+
801  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
+
802  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
+
803  long long int locNumAmps = qureg.numAmpsPerChunk;
+
804  long long int globalStartInd = qureg.chunkId * locNumAmps;
+
805  int innerBit = extractBit(measureQubit, globalStartInd);
+
806  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
+
807 
+
808  // If this chunk's amps are entirely inside an outer block
+
809  if (locNumAmps <= outerBlockSize) {
+
810 
+
811  // if this is an undesired outer block, kill all elems
+
812  if (outerBit != outcome) {
+
813  zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
+
814  return;
+
815  }
+
816 
+
817  // othwerwise, if this is a desired outer block, and also entirely an inner block
+
818  if (locNumAmps <= innerBlockSize) {
+
819 
+
820  // and that inner block is undesired, kill all elems
+
821  if (innerBit != outcome)
+
822  zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
+
823  // otherwise normalise all elems
+
824  else
+
825  normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
+
826 
+
827  return;
+
828  }
+
829 
+
830  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
+ +
832  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
+
833  return;
+
834  }
+
835 
+
836  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
+
837  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
+
838  long long int firstBlockInd;
+
839 
+
840  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
+
841  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
+
842  // inner parallelisation
+
843  if (outerBit == outcome) {
+
844 
+
845  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
+
846  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
+
847 
+
848  // *norm only the desired inner blocks in the desired outer block
+ +
850  qureg, totalStateProb, innerBit==outcome,
+
851  firstBlockInd, outerBlockSize, innerBlockSize);
+
852 
+
853  // zero the undesired outer block
+
854  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
+
855  }
+
856 
+
857  } else {
+
858 
+
859  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
+
860  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
+
861 
+
862  // same thing but undesired outer blocks come first
+
863  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
+ +
865  qureg, totalStateProb, innerBit==outcome,
+
866  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
+
867  }
+
868  }
+
869 
+
870 }
+
871 
+ +
873 
+
874  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
+
875  long long int index;
+
876  long long int numAmps = qureg.numAmpsPerChunk;
+
877 
+
878  qreal trace = 0;
+
879  qreal *vecRe = qureg.stateVec.real;
+
880  qreal *vecIm = qureg.stateVec.imag;
+
881 
+
882 # ifdef _OPENMP
+
883 # pragma omp parallel \
+
884  shared (vecRe, vecIm, numAmps) \
+
885  private (index) \
+
886  reduction ( +:trace )
+
887 # endif
+
888  {
+
889 # ifdef _OPENMP
+
890 # pragma omp for schedule (static)
+
891 # endif
+
892  for (index=0LL; index<numAmps; index++) {
+
893 
+
894  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
+
895  }
+
896  }
+
897 
+
898  return trace;
+
899 }
+
900 
+
901 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
+
902 
+
903  /* corresponding amplitudes live on the same node (same dimensions) */
+
904 
+
905  // unpack vars for OpenMP
+
906  qreal* combineVecRe = combineQureg.stateVec.real;
+
907  qreal* combineVecIm = combineQureg.stateVec.imag;
+
908  qreal* otherVecRe = otherQureg.stateVec.real;
+
909  qreal* otherVecIm = otherQureg.stateVec.imag;
+
910  long long int numAmps = combineQureg.numAmpsPerChunk;
+
911  long long int index;
+
912 
+
913 # ifdef _OPENMP
+
914 # pragma omp parallel \
+
915  default (none) \
+
916  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
+
917  private (index)
+
918 # endif
+
919  {
+
920 # ifdef _OPENMP
+
921 # pragma omp for schedule (static)
+
922 # endif
+
923  for (index=0; index < numAmps; index++) {
+
924  combineVecRe[index] *= 1-otherProb;
+
925  combineVecIm[index] *= 1-otherProb;
+
926 
+
927  combineVecRe[index] += otherProb * otherVecRe[index];
+
928  combineVecIm[index] += otherProb * otherVecIm[index];
+
929  }
+
930  }
+
931 }
+
932 
+
935 
-
936 # ifdef _OPENMP
-
937 # pragma omp parallel \
-
938  shared (aRe,aIm, bRe,bIm, numAmps) \
-
939  private (index,difRe,difIm) \
-
940  reduction ( +:trace )
-
941 # endif
-
942  {
-
943 # ifdef _OPENMP
-
944 # pragma omp for schedule (static)
-
945 # endif
-
946  for (index=0LL; index<numAmps; index++) {
-
947 
-
948  difRe = aRe[index] - bRe[index];
-
949  difIm = aIm[index] - bIm[index];
-
950  trace += difRe*difRe + difIm*difIm;
-
951  }
-
952  }
-
953 
-
954  return trace;
-
955 }
-
956 
- -
959 
-
960  long long int index;
-
961  long long int numAmps = a.numAmpsPerChunk;
-
962 
-
963  qreal *aRe = a.stateVec.real;
-
964  qreal *aIm = a.stateVec.imag;
-
965  qreal *bRe = b.stateVec.real;
-
966  qreal *bIm = b.stateVec.imag;
-
967 
-
968  qreal trace = 0;
-
969 
-
970 # ifdef _OPENMP
-
971 # pragma omp parallel \
-
972  shared (aRe,aIm, bRe,bIm, numAmps) \
-
973  private (index) \
-
974  reduction ( +:trace )
-
975 # endif
-
976  {
-
977 # ifdef _OPENMP
-
978 # pragma omp for schedule (static)
-
979 # endif
-
980  for (index=0LL; index<numAmps; index++) {
-
981  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
-
982  }
-
983  }
-
984 
-
985  return trace;
-
986 }
-
987 
-
988 
- -
991 
-
992  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
-
993  * We only consult the attributes.
-
994  *
-
995  * qureg is a density matrix, and pureState is a statevector.
-
996  * Every node contains as many columns of qureg as amps by pureState.
-
997  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
-
998  * Ergo, this node contains columns:
-
999  * qureg.chunkID * pureState.numAmpsPerChunk to
-
1000  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
-
1001  *
-
1002  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
-
1003  * entire pureState state-vector
-
1004  */
-
1005 
-
1006  // unpack everything for OPENMP
-
1007  qreal* vecRe = qureg.pairStateVec.real;
-
1008  qreal* vecIm = qureg.pairStateVec.imag;
-
1009  qreal* densRe = qureg.stateVec.real;
-
1010  qreal* densIm = qureg.stateVec.imag;
-
1011 
-
1012  int row, col;
-
1013  int dim = (int) pureState.numAmpsTotal;
-
1014  int colsPerNode = (int) pureState.numAmpsPerChunk;
-
1015  // using only int, because density matrix has squared as many amps so its
-
1016  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
-
1017 
-
1018  // starting GLOBAL column index of the qureg columns on this node
-
1019  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
-
1020 
-
1021  qreal densElemRe, densElemIm;
-
1022  qreal prefacRe, prefacIm;
-
1023  qreal rowSumRe, rowSumIm;
-
1024  qreal vecElemRe, vecElemIm;
-
1025 
-
1026  // quantity computed by this node
-
1027  qreal globalSumRe = 0; // imag-component is assumed zero
+
936  long long int index;
+
937  long long int numAmps = a.numAmpsPerChunk;
+
938 
+
939  qreal *aRe = a.stateVec.real;
+
940  qreal *aIm = a.stateVec.imag;
+
941  qreal *bRe = b.stateVec.real;
+
942  qreal *bIm = b.stateVec.imag;
+
943 
+
944  qreal trace = 0;
+
945  qreal difRe, difIm;
+
946 
+
947 # ifdef _OPENMP
+
948 # pragma omp parallel \
+
949  shared (aRe,aIm, bRe,bIm, numAmps) \
+
950  private (index,difRe,difIm) \
+
951  reduction ( +:trace )
+
952 # endif
+
953  {
+
954 # ifdef _OPENMP
+
955 # pragma omp for schedule (static)
+
956 # endif
+
957  for (index=0LL; index<numAmps; index++) {
+
958 
+
959  difRe = aRe[index] - bRe[index];
+
960  difIm = aIm[index] - bIm[index];
+
961  trace += difRe*difRe + difIm*difIm;
+
962  }
+
963  }
+
964 
+
965  return trace;
+
966 }
+
967 
+ +
970 
+
971  long long int index;
+
972  long long int numAmps = a.numAmpsPerChunk;
+
973 
+
974  qreal *aRe = a.stateVec.real;
+
975  qreal *aIm = a.stateVec.imag;
+
976  qreal *bRe = b.stateVec.real;
+
977  qreal *bIm = b.stateVec.imag;
+
978 
+
979  qreal trace = 0;
+
980 
+
981 # ifdef _OPENMP
+
982 # pragma omp parallel \
+
983  shared (aRe,aIm, bRe,bIm, numAmps) \
+
984  private (index) \
+
985  reduction ( +:trace )
+
986 # endif
+
987  {
+
988 # ifdef _OPENMP
+
989 # pragma omp for schedule (static)
+
990 # endif
+
991  for (index=0LL; index<numAmps; index++) {
+
992  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
+
993  }
+
994  }
+
995 
+
996  return trace;
+
997 }
+
998 
+
999 
+ +
1002 
+
1003  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
+
1004  * We only consult the attributes.
+
1005  *
+
1006  * qureg is a density matrix, and pureState is a statevector.
+
1007  * Every node contains as many columns of qureg as amps by pureState.
+
1008  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
+
1009  * Ergo, this node contains columns:
+
1010  * qureg.chunkID * pureState.numAmpsPerChunk to
+
1011  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
+
1012  *
+
1013  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
+
1014  * entire pureState state-vector
+
1015  */
+
1016 
+
1017  // unpack everything for OPENMP
+
1018  qreal* vecRe = qureg.pairStateVec.real;
+
1019  qreal* vecIm = qureg.pairStateVec.imag;
+
1020  qreal* densRe = qureg.stateVec.real;
+
1021  qreal* densIm = qureg.stateVec.imag;
+
1022 
+
1023  int row, col;
+
1024  int dim = (int) pureState.numAmpsTotal;
+
1025  int colsPerNode = (int) pureState.numAmpsPerChunk;
+
1026  // using only int, because density matrix has squared as many amps so its
+
1027  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
1028 
-
1029 # ifdef _OPENMP
-
1030 # pragma omp parallel \
-
1031  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
-
1032  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
-
1033  reduction ( +:globalSumRe )
-
1034 # endif
-
1035  {
-
1036 # ifdef _OPENMP
-
1037 # pragma omp for schedule (static)
-
1038 # endif
-
1039  // indices of my GLOBAL row
-
1040  for (row=0; row < dim; row++) {
-
1041 
-
1042  // single element of conj(pureState)
-
1043  prefacRe = vecRe[row];
-
1044  prefacIm = - vecIm[row];
-
1045 
-
1046  rowSumRe = 0;
-
1047  rowSumIm = 0;
-
1048 
-
1049  // indices of my LOCAL column
-
1050  for (col=0; col < colsPerNode; col++) {
-
1051 
-
1052  // my local density element
-
1053  densElemRe = densRe[row + dim*col];
-
1054  densElemIm = densIm[row + dim*col];
-
1055 
-
1056  // state-vector element
-
1057  vecElemRe = vecRe[startCol + col];
-
1058  vecElemIm = vecIm[startCol + col];
+
1029  // starting GLOBAL column index of the qureg columns on this node
+
1030  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
+
1031 
+
1032  qreal densElemRe, densElemIm;
+
1033  qreal prefacRe, prefacIm;
+
1034  qreal rowSumRe, rowSumIm;
+
1035  qreal vecElemRe, vecElemIm;
+
1036 
+
1037  // quantity computed by this node
+
1038  qreal globalSumRe = 0; // imag-component is assumed zero
+
1039 
+
1040 # ifdef _OPENMP
+
1041 # pragma omp parallel \
+
1042  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
+
1043  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
+
1044  reduction ( +:globalSumRe )
+
1045 # endif
+
1046  {
+
1047 # ifdef _OPENMP
+
1048 # pragma omp for schedule (static)
+
1049 # endif
+
1050  // indices of my GLOBAL row
+
1051  for (row=0; row < dim; row++) {
+
1052 
+
1053  // single element of conj(pureState)
+
1054  prefacRe = vecRe[row];
+
1055  prefacIm = - vecIm[row];
+
1056 
+
1057  rowSumRe = 0;
+
1058  rowSumIm = 0;
1059 
-
1060  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
-
1061  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
-
1062  }
-
1063 
-
1064  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
-
1065  }
-
1066  }
-
1067 
-
1068  return globalSumRe;
-
1069 }
-
1070 
- -
1072 
-
1073  qreal innerProdReal = 0;
-
1074  qreal innerProdImag = 0;
-
1075 
-
1076  long long int index;
-
1077  long long int numAmps = bra.numAmpsPerChunk;
-
1078  qreal *braVecReal = bra.stateVec.real;
-
1079  qreal *braVecImag = bra.stateVec.imag;
-
1080  qreal *ketVecReal = ket.stateVec.real;
-
1081  qreal *ketVecImag = ket.stateVec.imag;
-
1082 
-
1083  qreal braRe, braIm, ketRe, ketIm;
-
1084 
-
1085 # ifdef _OPENMP
-
1086 # pragma omp parallel \
-
1087  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
-
1088  private (index, braRe, braIm, ketRe, ketIm) \
-
1089  reduction ( +:innerProdReal, innerProdImag )
-
1090 # endif
-
1091  {
-
1092 # ifdef _OPENMP
-
1093 # pragma omp for schedule (static)
-
1094 # endif
-
1095  for (index=0; index < numAmps; index++) {
-
1096  braRe = braVecReal[index];
-
1097  braIm = braVecImag[index];
-
1098  ketRe = ketVecReal[index];
-
1099  ketIm = ketVecImag[index];
-
1100 
-
1101  // conj(bra_i) * ket_i
-
1102  innerProdReal += braRe*ketRe + braIm*ketIm;
-
1103  innerProdImag += braRe*ketIm - braIm*ketRe;
-
1104  }
-
1105  }
-
1106 
-
1107  Complex innerProd;
-
1108  innerProd.real = innerProdReal;
-
1109  innerProd.imag = innerProdImag;
-
1110  return innerProd;
-
1111 }
-
1112 
-
1113 
-
1114 
-
1115 void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
-
1116 {
-
1117  // dimension of the state vector
-
1118  long long int densityNumElems = qureg.numAmpsPerChunk;
-
1119 
-
1120  // Can't use qureg->stateVec as a private OMP var
-
1121  qreal *densityReal = qureg.stateVec.real;
-
1122  qreal *densityImag = qureg.stateVec.imag;
+
1060  // indices of my LOCAL column
+
1061  for (col=0; col < colsPerNode; col++) {
+
1062 
+
1063  // my local density element
+
1064  densElemRe = densRe[row + dim*col];
+
1065  densElemIm = densIm[row + dim*col];
+
1066 
+
1067  // state-vector element
+
1068  vecElemRe = vecRe[startCol + col];
+
1069  vecElemIm = vecIm[startCol + col];
+
1070 
+
1071  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
+
1072  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
+
1073  }
+
1074 
+
1075  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
+
1076  }
+
1077  }
+
1078 
+
1079  return globalSumRe;
+
1080 }
+
1081 
+ +
1083 
+
1084  qreal innerProdReal = 0;
+
1085  qreal innerProdImag = 0;
+
1086 
+
1087  long long int index;
+
1088  long long int numAmps = bra.numAmpsPerChunk;
+
1089  qreal *braVecReal = bra.stateVec.real;
+
1090  qreal *braVecImag = bra.stateVec.imag;
+
1091  qreal *ketVecReal = ket.stateVec.real;
+
1092  qreal *ketVecImag = ket.stateVec.imag;
+
1093 
+
1094  qreal braRe, braIm, ketRe, ketIm;
+
1095 
+
1096 # ifdef _OPENMP
+
1097 # pragma omp parallel \
+
1098  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
+
1099  private (index, braRe, braIm, ketRe, ketIm) \
+
1100  reduction ( +:innerProdReal, innerProdImag )
+
1101 # endif
+
1102  {
+
1103 # ifdef _OPENMP
+
1104 # pragma omp for schedule (static)
+
1105 # endif
+
1106  for (index=0; index < numAmps; index++) {
+
1107  braRe = braVecReal[index];
+
1108  braIm = braVecImag[index];
+
1109  ketRe = ketVecReal[index];
+
1110  ketIm = ketVecImag[index];
+
1111 
+
1112  // conj(bra_i) * ket_i
+
1113  innerProdReal += braRe*ketRe + braIm*ketIm;
+
1114  innerProdImag += braRe*ketIm - braIm*ketRe;
+
1115  }
+
1116  }
+
1117 
+
1118  Complex innerProd;
+
1119  innerProd.real = innerProdReal;
+
1120  innerProd.imag = innerProdImag;
+
1121  return innerProd;
+
1122 }
1123 
-
1124  // initialise the state to all zeros
-
1125  long long int index;
-
1126 # ifdef _OPENMP
-
1127 # pragma omp parallel \
-
1128  default (none) \
-
1129  shared (densityNumElems, densityReal, densityImag) \
-
1130  private (index)
-
1131 # endif
-
1132  {
-
1133 # ifdef _OPENMP
-
1134 # pragma omp for schedule (static)
-
1135 # endif
-
1136  for (index=0; index<densityNumElems; index++) {
-
1137  densityReal[index] = 0.0;
-
1138  densityImag[index] = 0.0;
-
1139  }
-
1140  }
-
1141 
-
1142  // index of the single density matrix elem to set non-zero
-
1143  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1144  long long int densityInd = (densityDim + 1)*stateInd;
-
1145 
-
1146  // give the specified classical state prob 1
-
1147  if (qureg.chunkId == densityInd / densityNumElems){
-
1148  densityReal[densityInd % densityNumElems] = 1.0;
-
1149  densityImag[densityInd % densityNumElems] = 0.0;
-
1150  }
-
1151 }
-
1152 
-
1153 
- -
1155 {
-
1156  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
-
1157  long long int dim = (1LL << qureg.numQubitsRepresented);
-
1158  qreal probFactor = 1.0/((qreal) dim);
-
1159 
-
1160  // Can't use qureg->stateVec as a private OMP var
-
1161  qreal *densityReal = qureg.stateVec.real;
-
1162  qreal *densityImag = qureg.stateVec.imag;
+
1124 
+
1125 
+
1126 void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
+
1127 {
+
1128  // dimension of the state vector
+
1129  long long int densityNumElems = qureg.numAmpsPerChunk;
+
1130 
+
1131  // Can't use qureg->stateVec as a private OMP var
+
1132  qreal *densityReal = qureg.stateVec.real;
+
1133  qreal *densityImag = qureg.stateVec.imag;
+
1134 
+
1135  // initialise the state to all zeros
+
1136  long long int index;
+
1137 # ifdef _OPENMP
+
1138 # pragma omp parallel \
+
1139  default (none) \
+
1140  shared (densityNumElems, densityReal, densityImag) \
+
1141  private (index)
+
1142 # endif
+
1143  {
+
1144 # ifdef _OPENMP
+
1145 # pragma omp for schedule (static)
+
1146 # endif
+
1147  for (index=0; index<densityNumElems; index++) {
+
1148  densityReal[index] = 0.0;
+
1149  densityImag[index] = 0.0;
+
1150  }
+
1151  }
+
1152 
+
1153  // index of the single density matrix elem to set non-zero
+
1154  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
1155  long long int densityInd = (densityDim + 1)*stateInd;
+
1156 
+
1157  // give the specified classical state prob 1
+
1158  if (qureg.chunkId == densityInd / densityNumElems){
+
1159  densityReal[densityInd % densityNumElems] = 1.0;
+
1160  densityImag[densityInd % densityNumElems] = 0.0;
+
1161  }
+
1162 }
1163 
-
1164  long long int index;
-
1165  long long int chunkSize = qureg.numAmpsPerChunk;
-
1166  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1167 # ifdef _OPENMP
-
1168 # pragma omp parallel \
-
1169  default (none) \
-
1170  shared (chunkSize, densityReal, densityImag, probFactor) \
-
1171  private (index)
-
1172 # endif
-
1173  {
-
1174 # ifdef _OPENMP
-
1175 # pragma omp for schedule (static)
-
1176 # endif
-
1177  for (index=0; index<chunkSize; index++) {
-
1178  densityReal[index] = probFactor;
-
1179  densityImag[index] = 0.0;
-
1180  }
-
1181  }
-
1182 }
-
1183 
-
1184 void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg) {
-
1185 
-
1186  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
-
1187  * which contains the full pure statevector.
-
1188  * targetQureg has as many columns on node as copyQureg has amps
-
1189  */
-
1190 
-
1191  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
-
1192  long long int colsPerNode = copyQureg.numAmpsPerChunk;
-
1193  long long int rowsPerNode = copyQureg.numAmpsTotal;
-
1194 
-
1195  // unpack vars for OpenMP
-
1196  qreal* vecRe = targetQureg.pairStateVec.real;
-
1197  qreal* vecIm = targetQureg.pairStateVec.imag;
-
1198  qreal* densRe = targetQureg.stateVec.real;
-
1199  qreal* densIm = targetQureg.stateVec.imag;
-
1200 
-
1201  long long int col, row, index;
-
1202 
-
1203  // a_i conj(a_j) |i><j|
-
1204  qreal ketRe, ketIm, braRe, braIm;
+
1164 
+ +
1166 {
+
1167  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
+
1168  long long int dim = (1LL << qureg.numQubitsRepresented);
+
1169  qreal probFactor = 1.0/((qreal) dim);
+
1170 
+
1171  // Can't use qureg->stateVec as a private OMP var
+
1172  qreal *densityReal = qureg.stateVec.real;
+
1173  qreal *densityImag = qureg.stateVec.imag;
+
1174 
+
1175  long long int index;
+
1176  long long int chunkSize = qureg.numAmpsPerChunk;
+
1177  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
+
1178 # ifdef _OPENMP
+
1179 # pragma omp parallel \
+
1180  default (none) \
+
1181  shared (chunkSize, densityReal, densityImag, probFactor) \
+
1182  private (index)
+
1183 # endif
+
1184  {
+
1185 # ifdef _OPENMP
+
1186 # pragma omp for schedule (static)
+
1187 # endif
+
1188  for (index=0; index<chunkSize; index++) {
+
1189  densityReal[index] = probFactor;
+
1190  densityImag[index] = 0.0;
+
1191  }
+
1192  }
+
1193 }
+
1194 
+
1195 void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg) {
+
1196 
+
1197  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
+
1198  * which contains the full pure statevector.
+
1199  * targetQureg has as many columns on node as copyQureg has amps
+
1200  */
+
1201 
+
1202  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
+
1203  long long int colsPerNode = copyQureg.numAmpsPerChunk;
+
1204  long long int rowsPerNode = copyQureg.numAmpsTotal;
1205 
-
1206 # ifdef _OPENMP
-
1207 # pragma omp parallel \
-
1208  default (none) \
-
1209  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
-
1210  private (col,row, ketRe,ketIm,braRe,braIm, index)
-
1211 # endif
-
1212  {
-
1213 # ifdef _OPENMP
-
1214 # pragma omp for schedule (static)
-
1215 # endif
-
1216  // local column
-
1217  for (col=0; col < colsPerNode; col++) {
-
1218 
-
1219  // global row
-
1220  for (row=0; row < rowsPerNode; row++) {
-
1221 
-
1222  // get pure state amps
-
1223  ketRe = vecRe[row];
-
1224  ketIm = vecIm[row];
-
1225  braRe = vecRe[col + colOffset];
-
1226  braIm = - vecIm[col + colOffset]; // minus for conjugation
-
1227 
-
1228  // update density matrix
-
1229  index = row + col*rowsPerNode; // local ind
-
1230  densRe[index] = ketRe*braRe - ketIm*braIm;
-
1231  densIm[index] = ketRe*braIm + ketIm*braRe;
-
1232  }
-
1233  }
-
1234  }
-
1235 }
-
1236 
-
1237 void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
-
1238 
-
1239  /* this is actually distributed, since the user's code runs on every node */
-
1240 
-
1241  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
1242  // these may be negative or above qureg.numAmpsPerChunk
-
1243  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
-
1244  long long int localEndInd = localStartInd + numAmps; // exclusive
-
1245 
-
1246  // add this to a local index to get corresponding elem in reals & imags
-
1247  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
-
1248 
-
1249  // restrict these indices to fit into this chunk
-
1250  if (localStartInd < 0)
-
1251  localStartInd = 0;
-
1252  if (localEndInd > qureg.numAmpsPerChunk)
-
1253  localEndInd = qureg.numAmpsPerChunk;
-
1254  // they may now be out of order = no iterations
-
1255 
-
1256  // unpacking OpenMP vars
-
1257  long long int index;
-
1258  qreal* vecRe = qureg.stateVec.real;
-
1259  qreal* vecIm = qureg.stateVec.imag;
-
1260 
-
1261 # ifdef _OPENMP
-
1262 # pragma omp parallel \
-
1263  default (none) \
-
1264  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
-
1265  private (index)
-
1266 # endif
-
1267  {
-
1268 # ifdef _OPENMP
-
1269 # pragma omp for schedule (static)
-
1270 # endif
-
1271  // iterate these local inds - this might involve no iterations
-
1272  for (index=localStartInd; index < localEndInd; index++) {
-
1273  vecRe[index] = reals[index + offset];
-
1274  vecIm[index] = imags[index + offset];
-
1275  }
-
1276  }
-
1277 }
-
1278 
-
1279 void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
-
1280 {
-
1281  long long int numAmps = 1LL << numQubits;
-
1282  long long int numAmpsPerRank = numAmps/env.numRanks;
-
1283 
-
1284  if (numAmpsPerRank > SIZE_MAX) {
-
1285  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
-
1286  exit (EXIT_FAILURE);
+
1206  // unpack vars for OpenMP
+
1207  qreal* vecRe = targetQureg.pairStateVec.real;
+
1208  qreal* vecIm = targetQureg.pairStateVec.imag;
+
1209  qreal* densRe = targetQureg.stateVec.real;
+
1210  qreal* densIm = targetQureg.stateVec.imag;
+
1211 
+
1212  long long int col, row, index;
+
1213 
+
1214  // a_i conj(a_j) |i><j|
+
1215  qreal ketRe, ketIm, braRe, braIm;
+
1216 
+
1217 # ifdef _OPENMP
+
1218 # pragma omp parallel \
+
1219  default (none) \
+
1220  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
+
1221  private (col,row, ketRe,ketIm,braRe,braIm, index)
+
1222 # endif
+
1223  {
+
1224 # ifdef _OPENMP
+
1225 # pragma omp for schedule (static)
+
1226 # endif
+
1227  // local column
+
1228  for (col=0; col < colsPerNode; col++) {
+
1229 
+
1230  // global row
+
1231  for (row=0; row < rowsPerNode; row++) {
+
1232 
+
1233  // get pure state amps
+
1234  ketRe = vecRe[row];
+
1235  ketIm = vecIm[row];
+
1236  braRe = vecRe[col + colOffset];
+
1237  braIm = - vecIm[col + colOffset]; // minus for conjugation
+
1238 
+
1239  // update density matrix
+
1240  index = row + col*rowsPerNode; // local ind
+
1241  densRe[index] = ketRe*braRe - ketIm*braIm;
+
1242  densIm[index] = ketRe*braIm + ketIm*braRe;
+
1243  }
+
1244  }
+
1245  }
+
1246 }
+
1247 
+
1248 void statevec_setAmps(Qureg qureg, long long int startInd, qreal* reals, qreal* imags, long long int numAmps) {
+
1249 
+
1250  /* this is actually distributed, since the user's code runs on every node */
+
1251 
+
1252  // local start/end indices of the given amplitudes, assuming they fit in this chunk
+
1253  // these may be negative or above qureg.numAmpsPerChunk
+
1254  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
+
1255  long long int localEndInd = localStartInd + numAmps; // exclusive
+
1256 
+
1257  // add this to a local index to get corresponding elem in reals & imags
+
1258  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
+
1259 
+
1260  // restrict these indices to fit into this chunk
+
1261  if (localStartInd < 0)
+
1262  localStartInd = 0;
+
1263  if (localEndInd > qureg.numAmpsPerChunk)
+
1264  localEndInd = qureg.numAmpsPerChunk;
+
1265  // they may now be out of order = no iterations
+
1266 
+
1267  // unpacking OpenMP vars
+
1268  long long int index;
+
1269  qreal* vecRe = qureg.stateVec.real;
+
1270  qreal* vecIm = qureg.stateVec.imag;
+
1271 
+
1272 # ifdef _OPENMP
+
1273 # pragma omp parallel \
+
1274  default (none) \
+
1275  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
+
1276  private (index)
+
1277 # endif
+
1278  {
+
1279 # ifdef _OPENMP
+
1280 # pragma omp for schedule (static)
+
1281 # endif
+
1282  // iterate these local inds - this might involve no iterations
+
1283  for (index=localStartInd; index < localEndInd; index++) {
+
1284  vecRe[index] = reals[index + offset];
+
1285  vecIm[index] = imags[index + offset];
+
1286  }
1287  }
-
1288 
-
1289  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
-
1290  qureg->stateVec.real = malloc(arrSize);
-
1291  qureg->stateVec.imag = malloc(arrSize);
-
1292  if (env.numRanks>1){
-
1293  qureg->pairStateVec.real = malloc(arrSize);
-
1294  qureg->pairStateVec.imag = malloc(arrSize);
-
1295  }
-
1296 
-
1297  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
1298  && numAmpsPerRank ) {
-
1299  printf("Could not allocate memory!");
-
1300  exit (EXIT_FAILURE);
-
1301  }
-
1302 
-
1303  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
1304  && numAmpsPerRank ) {
-
1305  printf("Could not allocate memory!");
-
1306  exit (EXIT_FAILURE);
-
1307  }
-
1308 
-
1309  qureg->numQubitsInStateVec = numQubits;
-
1310  qureg->numAmpsTotal = numAmps;
-
1311  qureg->numAmpsPerChunk = numAmpsPerRank;
-
1312  qureg->chunkId = env.rank;
-
1313  qureg->numChunks = env.numRanks;
-
1314  qureg->isDensityMatrix = 0;
-
1315 }
-
1316 
- -
1318 
-
1319  qureg.numQubitsInStateVec = 0;
-
1320  qureg.numAmpsTotal = 0;
-
1321  qureg.numAmpsPerChunk = 0;
-
1322 
-
1323  free(qureg.stateVec.real);
-
1324  free(qureg.stateVec.imag);
-
1325  if (env.numRanks>1){
-
1326  free(qureg.pairStateVec.real);
-
1327  free(qureg.pairStateVec.imag);
-
1328  }
-
1329  qureg.stateVec.real = NULL;
-
1330  qureg.stateVec.imag = NULL;
-
1331  qureg.pairStateVec.real = NULL;
-
1332  qureg.pairStateVec.imag = NULL;
-
1333 }
-
1334 
- -
1336 
-
1337  // the 2^numQubits values will be evenly split between the env.numRanks nodes
-
1338  DiagonalOp op;
-
1339  op.numQubits = numQubits;
-
1340  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
1341  op.chunkId = env.rank;
-
1342  op.numChunks = env.numRanks;
-
1343 
-
1344  // allocate CPU memory (initialised to zero)
-
1345  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1346  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1288 }
+
1289 
+
1290 void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
+
1291 {
+
1292  long long int numAmps = 1LL << numQubits;
+
1293  long long int numAmpsPerRank = numAmps/env.numRanks;
+
1294 
+
1295  if (numAmpsPerRank > SIZE_MAX) {
+
1296  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
+
1297  exit (EXIT_FAILURE);
+
1298  }
+
1299 
+
1300  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
+
1301  qureg->stateVec.real = malloc(arrSize);
+
1302  qureg->stateVec.imag = malloc(arrSize);
+
1303  if (env.numRanks>1){
+
1304  qureg->pairStateVec.real = malloc(arrSize);
+
1305  qureg->pairStateVec.imag = malloc(arrSize);
+
1306  }
+
1307 
+
1308  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
+
1309  && numAmpsPerRank ) {
+
1310  printf("Could not allocate memory!");
+
1311  exit (EXIT_FAILURE);
+
1312  }
+
1313 
+
1314  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
+
1315  && numAmpsPerRank ) {
+
1316  printf("Could not allocate memory!");
+
1317  exit (EXIT_FAILURE);
+
1318  }
+
1319 
+
1320  qureg->numQubitsInStateVec = numQubits;
+
1321  qureg->numAmpsTotal = numAmps;
+
1322  qureg->numAmpsPerChunk = numAmpsPerRank;
+
1323  qureg->chunkId = env.rank;
+
1324  qureg->numChunks = env.numRanks;
+
1325  qureg->isDensityMatrix = 0;
+
1326 }
+
1327 
+ +
1329 
+
1330  qureg.numQubitsInStateVec = 0;
+
1331  qureg.numAmpsTotal = 0;
+
1332  qureg.numAmpsPerChunk = 0;
+
1333 
+
1334  free(qureg.stateVec.real);
+
1335  free(qureg.stateVec.imag);
+
1336  if (env.numRanks>1){
+
1337  free(qureg.pairStateVec.real);
+
1338  free(qureg.pairStateVec.imag);
+
1339  }
+
1340  qureg.stateVec.real = NULL;
+
1341  qureg.stateVec.imag = NULL;
+
1342  qureg.pairStateVec.real = NULL;
+
1343  qureg.pairStateVec.imag = NULL;
+
1344 }
+
1345 
+
1347 
-
1348  // check cpu memory allocation was successful
-
1349  if ( !op.real || !op.imag ) {
-
1350  printf("Could not allocate memory!\n");
-
1351  exit(EXIT_FAILURE);
-
1352  }
-
1353 
-
1354  return op;
-
1355 }
-
1356 
- -
1358  free(op.real);
-
1359  free(op.imag);
-
1360 }
-
1361 
- -
1363  // nothing to do on CPU
-
1364 }
-
1365 
- -
1367 
-
1368  /* each node modifies its op sub-partition, evaluating the full hamil
-
1369  * for every element in the sub-partition
-
1370  */
-
1371 
-
1372  // unpack op
-
1373  long long int offset = op.chunkId * op.numElemsPerChunk;
-
1374  long long int numElems = op.numElemsPerChunk;
-
1375  qreal* opRe = op.real;
-
1376  qreal* opIm = op.imag;
-
1377 
-
1378  // unpack hamil
-
1379  int numTerms = hamil.numSumTerms;
-
1380  int numQubits = hamil.numQubits;
-
1381  qreal* coeffs = hamil.termCoeffs;
-
1382  enum pauliOpType* codes = hamil.pauliCodes;
-
1383 
-
1384  // private OpenMP vars
-
1385  long long int i, globalInd;
-
1386  qreal elem;
-
1387  int t, q, isOddNumOnes, sign;
+
1348  // the 2^numQubits values will be evenly split between the env.numRanks nodes
+
1349  DiagonalOp op;
+
1350  op.numQubits = numQubits;
+
1351  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
+
1352  op.chunkId = env.rank;
+
1353  op.numChunks = env.numRanks;
+
1354 
+
1355  // allocate CPU memory (initialised to zero)
+
1356  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1357  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1358 
+
1359  // check cpu memory allocation was successful
+
1360  if ( !op.real || !op.imag ) {
+
1361  printf("Could not allocate memory!\n");
+
1362  exit(EXIT_FAILURE);
+
1363  }
+
1364 
+
1365  return op;
+
1366 }
+
1367 
+ +
1369  free(op.real);
+
1370  free(op.imag);
+
1371 }
+
1372 
+ +
1374  // nothing to do on CPU
+
1375 }
+
1376 
+ +
1378 
+
1379  /* each node modifies its op sub-partition, evaluating the full hamil
+
1380  * for every element in the sub-partition
+
1381  */
+
1382 
+
1383  // unpack op
+
1384  long long int offset = op.chunkId * op.numElemsPerChunk;
+
1385  long long int numElems = op.numElemsPerChunk;
+
1386  qreal* opRe = op.real;
+
1387  qreal* opIm = op.imag;
1388 
-
1389 # ifdef _OPENMP
-
1390 # pragma omp parallel \
-
1391  default (none) \
-
1392  shared (offset,numElems, opRe,opIm, numTerms,numQubits,coeffs,codes) \
-
1393  private (i,globalInd, elem, isOddNumOnes,t,q,sign)
-
1394 # endif
-
1395  {
-
1396 # ifdef _OPENMP
-
1397 # pragma omp for schedule (static)
-
1398 # endif
-
1399  for (i=0; i<numElems; i++) {
-
1400 
-
1401  globalInd = i + offset;
-
1402  elem = 0;
-
1403 
-
1404  // add every Hamiltonian coefficient to this element, either + or -
-
1405  for (t=0; t<numTerms; t++) {
-
1406 
-
1407  // determine parity of ones (in globalInd basis state) of the current term's targets
-
1408  isOddNumOnes = 0;
-
1409  for (q=0; q<numQubits; q++)
-
1410  if (codes[q + t*numQubits] == PAULI_Z)
-
1411  if (extractBit(q, globalInd))
-
1412  isOddNumOnes = !isOddNumOnes;
-
1413 
-
1414  // add +- term coeff (avoiding thread divergence)
-
1415  sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1)
-
1416  elem += coeffs[t] * sign;
-
1417  }
-
1418 
-
1419  opRe[i] = elem;
-
1420  opIm[i] = 0;
-
1421  }
-
1422  }
-
1423 
-
1424  // we don't synch to GPU, because in GPU mode, the GPU populates and synchs to RAM
-
1425  // agnostic_syncDiagonalOp(op);
-
1426 }
-
1427 
-
1428 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank){
-
1429  long long int index;
-
1430  int rank;
-
1431  if (qureg.numQubitsInStateVec<=5){
-
1432  for (rank=0; rank<qureg.numChunks; rank++){
-
1433  if (qureg.chunkId==rank){
-
1434  if (reportRank) {
-
1435  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
1436  printf("real, imag\n");
-
1437  } else if (rank==0) {
-
1438  printf("Reporting state [\n");
-
1439  printf("real, imag\n");
-
1440  }
-
1441 
-
1442  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
1443  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
-
1444  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
1445  }
-
1446  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
1447  }
-
1448  syncQuESTEnv(env);
-
1449  }
-
1450  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
-
1451 }
+
1389  // unpack hamil
+
1390  int numTerms = hamil.numSumTerms;
+
1391  int numQubits = hamil.numQubits;
+
1392  qreal* coeffs = hamil.termCoeffs;
+
1393  enum pauliOpType* codes = hamil.pauliCodes;
+
1394 
+
1395  // private OpenMP vars
+
1396  long long int i, globalInd;
+
1397  qreal elem;
+
1398  int t, q, isOddNumOnes, sign;
+
1399 
+
1400 # ifdef _OPENMP
+
1401 # pragma omp parallel \
+
1402  default (none) \
+
1403  shared (offset,numElems, opRe,opIm, numTerms,numQubits,coeffs,codes) \
+
1404  private (i,globalInd, elem, isOddNumOnes,t,q,sign)
+
1405 # endif
+
1406  {
+
1407 # ifdef _OPENMP
+
1408 # pragma omp for schedule (static)
+
1409 # endif
+
1410  for (i=0; i<numElems; i++) {
+
1411 
+
1412  globalInd = i + offset;
+
1413  elem = 0;
+
1414 
+
1415  // add every Hamiltonian coefficient to this element, either + or -
+
1416  for (t=0; t<numTerms; t++) {
+
1417 
+
1418  // determine parity of ones (in globalInd basis state) of the current term's targets
+
1419  isOddNumOnes = 0;
+
1420  for (q=0; q<numQubits; q++)
+
1421  if (codes[q + t*numQubits] == PAULI_Z)
+
1422  if (extractBit(q, globalInd))
+
1423  isOddNumOnes = !isOddNumOnes;
+
1424 
+
1425  // add +- term coeff (avoiding thread divergence)
+
1426  sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1)
+
1427  elem += coeffs[t] * sign;
+
1428  }
+
1429 
+
1430  opRe[i] = elem;
+
1431  opIm[i] = 0;
+
1432  }
+
1433  }
+
1434 
+
1435  // we don't synch to GPU, because in GPU mode, the GPU populates and synchs to RAM
+
1436  // agnostic_syncDiagonalOp(op);
+
1437 }
+
1438 
+
1439 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank){
+
1440  long long int index;
+
1441  int rank;
+
1442  if (qureg.numQubitsInStateVec<=5){
+
1443  for (rank=0; rank<qureg.numChunks; rank++){
+
1444  if (qureg.chunkId==rank){
+
1445  if (reportRank) {
+
1446  printf("Reporting state from rank %d [\n", qureg.chunkId);
+
1447  printf("real, imag\n");
+
1448  } else if (rank==0) {
+
1449  printf("Reporting state [\n");
+
1450  printf("real, imag\n");
+
1451  }
1452 
- -
1454 {
-
1455  long long int stateVecSize;
-
1456  long long int index;
-
1457 
-
1458  // dimension of the state vector
-
1459  stateVecSize = qureg.numAmpsPerChunk;
-
1460 
-
1461  // Can't use qureg->stateVec as a private OMP var
-
1462  qreal *stateVecReal = qureg.stateVec.real;
-
1463  qreal *stateVecImag = qureg.stateVec.imag;
-
1464 
-
1465  // initialise the state-vector to all-zeroes
-
1466 # ifdef _OPENMP
-
1467 # pragma omp parallel \
-
1468  default (none) \
-
1469  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1470  private (index)
-
1471 # endif
-
1472  {
-
1473 # ifdef _OPENMP
-
1474 # pragma omp for schedule (static)
-
1475 # endif
-
1476  for (index=0; index<stateVecSize; index++) {
-
1477  stateVecReal[index] = 0.0;
-
1478  stateVecImag[index] = 0.0;
-
1479  }
-
1480  }
-
1481 }
-
1482 
- -
1484 {
-
1485  statevec_initBlankState(qureg);
-
1486  if (qureg.chunkId==0){
-
1487  // zero state |0000..0000> has probability 1
-
1488  qureg.stateVec.real[0] = 1.0;
-
1489  qureg.stateVec.imag[0] = 0.0;
-
1490  }
-
1491 }
-
1492 
- -
1494 {
-
1495  long long int chunkSize, stateVecSize;
-
1496  long long int index;
-
1497 
-
1498  // dimension of the state vector
-
1499  chunkSize = qureg.numAmpsPerChunk;
-
1500  stateVecSize = chunkSize*qureg.numChunks;
-
1501  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
1502 
-
1503  // Can't use qureg->stateVec as a private OMP var
-
1504  qreal *stateVecReal = qureg.stateVec.real;
-
1505  qreal *stateVecImag = qureg.stateVec.imag;
-
1506 
-
1507  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1508 # ifdef _OPENMP
-
1509 # pragma omp parallel \
-
1510  default (none) \
-
1511  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
-
1512  private (index)
-
1513 # endif
-
1514  {
-
1515 # ifdef _OPENMP
-
1516 # pragma omp for schedule (static)
-
1517 # endif
-
1518  for (index=0; index<chunkSize; index++) {
-
1519  stateVecReal[index] = normFactor;
-
1520  stateVecImag[index] = 0.0;
-
1521  }
-
1522  }
-
1523 }
-
1524 
-
1525 void statevec_initClassicalState (Qureg qureg, long long int stateInd)
-
1526 {
-
1527  long long int stateVecSize;
-
1528  long long int index;
-
1529 
-
1530  // dimension of the state vector
-
1531  stateVecSize = qureg.numAmpsPerChunk;
-
1532 
-
1533  // Can't use qureg->stateVec as a private OMP var
-
1534  qreal *stateVecReal = qureg.stateVec.real;
-
1535  qreal *stateVecImag = qureg.stateVec.imag;
-
1536 
-
1537  // initialise the state to vector to all zeros
-
1538 # ifdef _OPENMP
-
1539 # pragma omp parallel \
-
1540  default (none) \
-
1541  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1542  private (index)
-
1543 # endif
-
1544  {
-
1545 # ifdef _OPENMP
-
1546 # pragma omp for schedule (static)
-
1547 # endif
-
1548  for (index=0; index<stateVecSize; index++) {
-
1549  stateVecReal[index] = 0.0;
-
1550  stateVecImag[index] = 0.0;
-
1551  }
-
1552  }
-
1553 
-
1554  // give the specified classical state prob 1
-
1555  if (qureg.chunkId == stateInd/stateVecSize){
-
1556  stateVecReal[stateInd % stateVecSize] = 1.0;
-
1557  stateVecImag[stateInd % stateVecSize] = 0.0;
-
1558  }
-
1559 }
-
1560 
-
1561 void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) {
-
1562 
-
1563  // registers are equal sized, so nodes hold the same state-vector partitions
-
1564  long long int stateVecSize;
-
1565  long long int index;
-
1566 
-
1567  // dimension of the state vector
-
1568  stateVecSize = targetQureg.numAmpsPerChunk;
-
1569 
-
1570  // Can't use qureg->stateVec as a private OMP var
-
1571  qreal *targetStateVecReal = targetQureg.stateVec.real;
-
1572  qreal *targetStateVecImag = targetQureg.stateVec.imag;
-
1573  qreal *copyStateVecReal = copyQureg.stateVec.real;
-
1574  qreal *copyStateVecImag = copyQureg.stateVec.imag;
-
1575 
-
1576  // initialise the state to |0000..0000>
-
1577 # ifdef _OPENMP
-
1578 # pragma omp parallel \
-
1579  default (none) \
-
1580  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
-
1581  private (index)
-
1582 # endif
-
1583  {
-
1584 # ifdef _OPENMP
-
1585 # pragma omp for schedule (static)
-
1586 # endif
-
1587  for (index=0; index<stateVecSize; index++) {
-
1588  targetStateVecReal[index] = copyStateVecReal[index];
-
1589  targetStateVecImag[index] = copyStateVecImag[index];
-
1590  }
-
1591  }
-
1592 }
-
1593 
-
1600 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
-
1601 {
-
1602  long long int chunkSize, stateVecSize;
-
1603  long long int index;
-
1604  int bit;
-
1605  long long int chunkId=qureg->chunkId;
-
1606 
-
1607  // dimension of the state vector
-
1608  chunkSize = qureg->numAmpsPerChunk;
-
1609  stateVecSize = chunkSize*qureg->numChunks;
-
1610  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
-
1611 
-
1612  // Can't use qureg->stateVec as a private OMP var
-
1613  qreal *stateVecReal = qureg->stateVec.real;
-
1614  qreal *stateVecImag = qureg->stateVec.imag;
-
1615 
-
1616  // initialise the state to |0000..0000>
-
1617 # ifdef _OPENMP
-
1618 # pragma omp parallel \
-
1619  default (none) \
-
1620  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
-
1621  private (index, bit)
-
1622 # endif
-
1623  {
-
1624 # ifdef _OPENMP
-
1625 # pragma omp for schedule (static)
-
1626 # endif
-
1627  for (index=0; index<chunkSize; index++) {
-
1628  bit = extractBit(qubitId, index+chunkId*chunkSize);
-
1629  if (bit==outcome) {
-
1630  stateVecReal[index] = normFactor;
-
1631  stateVecImag[index] = 0.0;
-
1632  } else {
-
1633  stateVecReal[index] = 0.0;
-
1634  stateVecImag[index] = 0.0;
-
1635  }
-
1636  }
-
1637  }
-
1638 }
-
1639 
-
1640 
- -
1647 {
-
1648  long long int chunkSize;
-
1649  long long int index;
-
1650  long long int indexOffset;
+
1453  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
1454  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
+
1455  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
1456  }
+
1457  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
+
1458  }
+
1459  syncQuESTEnv(env);
+
1460  }
+
1461  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
+
1462 }
+
1463 
+ +
1465 {
+
1466  long long int stateVecSize;
+
1467  long long int index;
+
1468 
+
1469  // dimension of the state vector
+
1470  stateVecSize = qureg.numAmpsPerChunk;
+
1471 
+
1472  // Can't use qureg->stateVec as a private OMP var
+
1473  qreal *stateVecReal = qureg.stateVec.real;
+
1474  qreal *stateVecImag = qureg.stateVec.imag;
+
1475 
+
1476  // initialise the state-vector to all-zeroes
+
1477 # ifdef _OPENMP
+
1478 # pragma omp parallel \
+
1479  default (none) \
+
1480  shared (stateVecSize, stateVecReal, stateVecImag) \
+
1481  private (index)
+
1482 # endif
+
1483  {
+
1484 # ifdef _OPENMP
+
1485 # pragma omp for schedule (static)
+
1486 # endif
+
1487  for (index=0; index<stateVecSize; index++) {
+
1488  stateVecReal[index] = 0.0;
+
1489  stateVecImag[index] = 0.0;
+
1490  }
+
1491  }
+
1492 }
+
1493 
+ +
1495 {
+
1496  statevec_initBlankState(qureg);
+
1497  if (qureg.chunkId==0){
+
1498  // zero state |0000..0000> has probability 1
+
1499  qureg.stateVec.real[0] = 1.0;
+
1500  qureg.stateVec.imag[0] = 0.0;
+
1501  }
+
1502 }
+
1503 
+ +
1505 {
+
1506  long long int chunkSize, stateVecSize;
+
1507  long long int index;
+
1508 
+
1509  // dimension of the state vector
+
1510  chunkSize = qureg.numAmpsPerChunk;
+
1511  stateVecSize = chunkSize*qureg.numChunks;
+
1512  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
+
1513 
+
1514  // Can't use qureg->stateVec as a private OMP var
+
1515  qreal *stateVecReal = qureg.stateVec.real;
+
1516  qreal *stateVecImag = qureg.stateVec.imag;
+
1517 
+
1518  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
+
1519 # ifdef _OPENMP
+
1520 # pragma omp parallel \
+
1521  default (none) \
+
1522  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
+
1523  private (index)
+
1524 # endif
+
1525  {
+
1526 # ifdef _OPENMP
+
1527 # pragma omp for schedule (static)
+
1528 # endif
+
1529  for (index=0; index<chunkSize; index++) {
+
1530  stateVecReal[index] = normFactor;
+
1531  stateVecImag[index] = 0.0;
+
1532  }
+
1533  }
+
1534 }
+
1535 
+
1536 void statevec_initClassicalState (Qureg qureg, long long int stateInd)
+
1537 {
+
1538  long long int stateVecSize;
+
1539  long long int index;
+
1540 
+
1541  // dimension of the state vector
+
1542  stateVecSize = qureg.numAmpsPerChunk;
+
1543 
+
1544  // Can't use qureg->stateVec as a private OMP var
+
1545  qreal *stateVecReal = qureg.stateVec.real;
+
1546  qreal *stateVecImag = qureg.stateVec.imag;
+
1547 
+
1548  // initialise the state to vector to all zeros
+
1549 # ifdef _OPENMP
+
1550 # pragma omp parallel \
+
1551  default (none) \
+
1552  shared (stateVecSize, stateVecReal, stateVecImag) \
+
1553  private (index)
+
1554 # endif
+
1555  {
+
1556 # ifdef _OPENMP
+
1557 # pragma omp for schedule (static)
+
1558 # endif
+
1559  for (index=0; index<stateVecSize; index++) {
+
1560  stateVecReal[index] = 0.0;
+
1561  stateVecImag[index] = 0.0;
+
1562  }
+
1563  }
+
1564 
+
1565  // give the specified classical state prob 1
+
1566  if (qureg.chunkId == stateInd/stateVecSize){
+
1567  stateVecReal[stateInd % stateVecSize] = 1.0;
+
1568  stateVecImag[stateInd % stateVecSize] = 0.0;
+
1569  }
+
1570 }
+
1571 
+
1572 void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg) {
+
1573 
+
1574  // registers are equal sized, so nodes hold the same state-vector partitions
+
1575  long long int stateVecSize;
+
1576  long long int index;
+
1577 
+
1578  // dimension of the state vector
+
1579  stateVecSize = targetQureg.numAmpsPerChunk;
+
1580 
+
1581  // Can't use qureg->stateVec as a private OMP var
+
1582  qreal *targetStateVecReal = targetQureg.stateVec.real;
+
1583  qreal *targetStateVecImag = targetQureg.stateVec.imag;
+
1584  qreal *copyStateVecReal = copyQureg.stateVec.real;
+
1585  qreal *copyStateVecImag = copyQureg.stateVec.imag;
+
1586 
+
1587  // initialise the state to |0000..0000>
+
1588 # ifdef _OPENMP
+
1589 # pragma omp parallel \
+
1590  default (none) \
+
1591  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
+
1592  private (index)
+
1593 # endif
+
1594  {
+
1595 # ifdef _OPENMP
+
1596 # pragma omp for schedule (static)
+
1597 # endif
+
1598  for (index=0; index<stateVecSize; index++) {
+
1599  targetStateVecReal[index] = copyStateVecReal[index];
+
1600  targetStateVecImag[index] = copyStateVecImag[index];
+
1601  }
+
1602  }
+
1603 }
+
1604 
+
1611 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
+
1612 {
+
1613  long long int chunkSize, stateVecSize;
+
1614  long long int index;
+
1615  int bit;
+
1616  long long int chunkId=qureg->chunkId;
+
1617 
+
1618  // dimension of the state vector
+
1619  chunkSize = qureg->numAmpsPerChunk;
+
1620  stateVecSize = chunkSize*qureg->numChunks;
+
1621  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
+
1622 
+
1623  // Can't use qureg->stateVec as a private OMP var
+
1624  qreal *stateVecReal = qureg->stateVec.real;
+
1625  qreal *stateVecImag = qureg->stateVec.imag;
+
1626 
+
1627  // initialise the state to |0000..0000>
+
1628 # ifdef _OPENMP
+
1629 # pragma omp parallel \
+
1630  default (none) \
+
1631  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
+
1632  private (index, bit)
+
1633 # endif
+
1634  {
+
1635 # ifdef _OPENMP
+
1636 # pragma omp for schedule (static)
+
1637 # endif
+
1638  for (index=0; index<chunkSize; index++) {
+
1639  bit = extractBit(qubitId, index+chunkId*chunkSize);
+
1640  if (bit==outcome) {
+
1641  stateVecReal[index] = normFactor;
+
1642  stateVecImag[index] = 0.0;
+
1643  } else {
+
1644  stateVecReal[index] = 0.0;
+
1645  stateVecImag[index] = 0.0;
+
1646  }
+
1647  }
+
1648  }
+
1649 }
+
1650 
1651 
-
1652  // dimension of the state vector
-
1653  chunkSize = qureg.numAmpsPerChunk;
-
1654 
-
1655  // Can't use qureg->stateVec as a private OMP var
-
1656  qreal *stateVecReal = qureg.stateVec.real;
-
1657  qreal *stateVecImag = qureg.stateVec.imag;
-
1658 
-
1659  indexOffset = chunkSize * qureg.chunkId;
-
1660 
-
1661  // initialise the state to |0000..0000>
-
1662 # ifdef _OPENMP
-
1663 # pragma omp parallel \
-
1664  default (none) \
-
1665  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
-
1666  private (index)
-
1667 # endif
-
1668  {
-
1669 # ifdef _OPENMP
-
1670 # pragma omp for schedule (static)
-
1671 # endif
-
1672  for (index=0; index<chunkSize; index++) {
-
1673  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
-
1674  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
-
1675  }
-
1676  }
-
1677 }
-
1678 
-
1679 // returns 1 if successful, else 0
-
1680 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
-
1681  long long int chunkSize, stateVecSize;
-
1682  long long int indexInChunk, totalIndex;
-
1683 
-
1684  chunkSize = qureg->numAmpsPerChunk;
-
1685  stateVecSize = chunkSize*qureg->numChunks;
-
1686 
-
1687  qreal *stateVecReal = qureg->stateVec.real;
-
1688  qreal *stateVecImag = qureg->stateVec.imag;
+ +
1658 {
+
1659  long long int chunkSize;
+
1660  long long int index;
+
1661  long long int indexOffset;
+
1662 
+
1663  // dimension of the state vector
+
1664  chunkSize = qureg.numAmpsPerChunk;
+
1665 
+
1666  // Can't use qureg->stateVec as a private OMP var
+
1667  qreal *stateVecReal = qureg.stateVec.real;
+
1668  qreal *stateVecImag = qureg.stateVec.imag;
+
1669 
+
1670  indexOffset = chunkSize * qureg.chunkId;
+
1671 
+
1672  // initialise the state to |0000..0000>
+
1673 # ifdef _OPENMP
+
1674 # pragma omp parallel \
+
1675  default (none) \
+
1676  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
+
1677  private (index)
+
1678 # endif
+
1679  {
+
1680 # ifdef _OPENMP
+
1681 # pragma omp for schedule (static)
+
1682 # endif
+
1683  for (index=0; index<chunkSize; index++) {
+
1684  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
+
1685  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
+
1686  }
+
1687  }
+
1688 }
1689 
-
1690  FILE *fp;
-
1691  char line[200];
-
1692 
-
1693  for (int rank=0; rank<(qureg->numChunks); rank++){
-
1694  if (rank==qureg->chunkId){
-
1695  fp = fopen(filename, "r");
-
1696 
-
1697  // indicate file open failure
-
1698  if (fp == NULL)
-
1699  return 0;
-
1700 
-
1701  indexInChunk = 0; totalIndex = 0;
-
1702  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
1703  if (line[0]!='#'){
-
1704  int chunkId = (int) (totalIndex/chunkSize);
-
1705  if (chunkId==qureg->chunkId){
-
1706  # if QuEST_PREC==1
-
1707  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
1708  &(stateVecImag[indexInChunk]));
-
1709  # elif QuEST_PREC==2
-
1710  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
1711  &(stateVecImag[indexInChunk]));
-
1712  # elif QuEST_PREC==4
-
1713  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
-
1714  &(stateVecImag[indexInChunk]));
-
1715  # endif
-
1716  indexInChunk += 1;
-
1717  }
-
1718  totalIndex += 1;
-
1719  }
-
1720  }
-
1721  fclose(fp);
-
1722  }
-
1723  syncQuESTEnv(env);
-
1724  }
-
1725 
-
1726  // indicate success
-
1727  return 1;
-
1728 }
-
1729 
-
1730 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
-
1731  qreal diff;
-
1732  long long int chunkSize = mq1.numAmpsPerChunk;
-
1733 
-
1734  for (long long int i=0; i<chunkSize; i++){
-
1735  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
-
1736  if (diff>precision) return 0;
-
1737  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
-
1738  if (diff>precision) return 0;
-
1739  }
-
1740  return 1;
-
1741 }
-
1742 
-
1743 void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
1744 {
-
1745  long long int sizeBlock, sizeHalfBlock;
-
1746  long long int thisBlock, // current block
-
1747  indexUp,indexLo; // current index and corresponding index in lower half block
-
1748 
-
1749  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1750  long long int thisTask;
-
1751  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1752 
-
1753  // set dimensions
-
1754  sizeHalfBlock = 1LL << targetQubit;
-
1755  sizeBlock = 2LL * sizeHalfBlock;
-
1756 
-
1757  // Can't use qureg.stateVec as a private OMP var
-
1758  qreal *stateVecReal = qureg.stateVec.real;
-
1759  qreal *stateVecImag = qureg.stateVec.imag;
-
1760  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
1761  qreal betaImag=beta.imag, betaReal=beta.real;
-
1762 
-
1763 # ifdef _OPENMP
-
1764 # pragma omp parallel \
-
1765  default (none) \
-
1766  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
-
1767  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1768 # endif
-
1769  {
-
1770 # ifdef _OPENMP
-
1771 # pragma omp for schedule (static)
-
1772 # endif
-
1773  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1774 
-
1775  thisBlock = thisTask / sizeHalfBlock;
-
1776  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1777  indexLo = indexUp + sizeHalfBlock;
-
1778 
-
1779  // store current state vector values in temp variables
-
1780  stateRealUp = stateVecReal[indexUp];
-
1781  stateImagUp = stateVecImag[indexUp];
-
1782 
-
1783  stateRealLo = stateVecReal[indexLo];
-
1784  stateImagLo = stateVecImag[indexLo];
+
1690 // returns 1 if successful, else 0
+
1691 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
+
1692  long long int chunkSize, stateVecSize;
+
1693  long long int indexInChunk, totalIndex;
+
1694 
+
1695  chunkSize = qureg->numAmpsPerChunk;
+
1696  stateVecSize = chunkSize*qureg->numChunks;
+
1697 
+
1698  qreal *stateVecReal = qureg->stateVec.real;
+
1699  qreal *stateVecImag = qureg->stateVec.imag;
+
1700 
+
1701  FILE *fp;
+
1702  char line[200];
+
1703 
+
1704  for (int rank=0; rank<(qureg->numChunks); rank++){
+
1705  if (rank==qureg->chunkId){
+
1706  fp = fopen(filename, "r");
+
1707 
+
1708  // indicate file open failure
+
1709  if (fp == NULL)
+
1710  return 0;
+
1711 
+
1712  indexInChunk = 0; totalIndex = 0;
+
1713  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
+
1714  if (line[0]!='#'){
+
1715  int chunkId = (int) (totalIndex/chunkSize);
+
1716  if (chunkId==qureg->chunkId){
+
1717  # if QuEST_PREC==1
+
1718  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
+
1719  &(stateVecImag[indexInChunk]));
+
1720  # elif QuEST_PREC==2
+
1721  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
1722  &(stateVecImag[indexInChunk]));
+
1723  # elif QuEST_PREC==4
+
1724  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
+
1725  &(stateVecImag[indexInChunk]));
+
1726  # endif
+
1727  indexInChunk += 1;
+
1728  }
+
1729  totalIndex += 1;
+
1730  }
+
1731  }
+
1732  fclose(fp);
+
1733  }
+
1734  syncQuESTEnv(env);
+
1735  }
+
1736 
+
1737  // indicate success
+
1738  return 1;
+
1739 }
+
1740 
+
1741 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
+
1742  qreal diff;
+
1743  long long int chunkSize = mq1.numAmpsPerChunk;
+
1744 
+
1745  for (long long int i=0; i<chunkSize; i++){
+
1746  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
+
1747  if (diff>precision) return 0;
+
1748  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
+
1749  if (diff>precision) return 0;
+
1750  }
+
1751  return 1;
+
1752 }
+
1753 
+
1754 void statevec_compactUnitaryLocal (Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
1755 {
+
1756  long long int sizeBlock, sizeHalfBlock;
+
1757  long long int thisBlock, // current block
+
1758  indexUp,indexLo; // current index and corresponding index in lower half block
+
1759 
+
1760  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
1761  long long int thisTask;
+
1762  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1763 
+
1764  // set dimensions
+
1765  sizeHalfBlock = 1LL << targetQubit;
+
1766  sizeBlock = 2LL * sizeHalfBlock;
+
1767 
+
1768  // Can't use qureg.stateVec as a private OMP var
+
1769  qreal *stateVecReal = qureg.stateVec.real;
+
1770  qreal *stateVecImag = qureg.stateVec.imag;
+
1771  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
1772  qreal betaImag=beta.imag, betaReal=beta.real;
+
1773 
+
1774 # ifdef _OPENMP
+
1775 # pragma omp parallel \
+
1776  default (none) \
+
1777  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
+
1778  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
1779 # endif
+
1780  {
+
1781 # ifdef _OPENMP
+
1782 # pragma omp for schedule (static)
+
1783 # endif
+
1784  for (thisTask=0; thisTask<numTasks; thisTask++) {
1785 
-
1786  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
1787  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
1788  - betaReal*stateRealLo - betaImag*stateImagLo;
-
1789  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
1790  - betaReal*stateImagLo + betaImag*stateRealLo;
-
1791 
-
1792  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
1793  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
1794  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
1795  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
1796  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
1797  }
-
1798  }
-
1799 
-
1800 }
-
1801 
-
1802 void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) {
-
1803 
-
1804  // can't use qureg.stateVec as a private OMP var
-
1805  qreal *reVec = qureg.stateVec.real;
-
1806  qreal *imVec = qureg.stateVec.imag;
-
1807 
-
1808  // the global (between all nodes) index of this node's start index
-
1809  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1810 
-
1811  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
-
1812  long long int thisTask;
-
1813  long long int thisGlobalInd00;
-
1814  long long int ind00, ind01, ind10, ind11;
-
1815  qreal re00, re01, re10, re11;
-
1816  qreal im00, im01, im10, im11;
-
1817 
-
1818 # ifdef _OPENMP
-
1819 # pragma omp parallel \
-
1820  default (none) \
-
1821  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
-
1822  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
-
1823 # endif
-
1824  {
-
1825 # ifdef _OPENMP
-
1826 # pragma omp for schedule (static)
-
1827 # endif
-
1828  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1829 
-
1830  // determine ind00 of |..0..0..>
-
1831  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1832 
-
1833  // skip amplitude if controls aren't in 1 state (overloaded for speed)
-
1834  thisGlobalInd00 = ind00 + globalIndStart;
-
1835  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1836  continue;
-
1837 
-
1838  // inds of |..0..1..>, |..1..0..> and |..1..1..>
-
1839  ind01 = flipBit(ind00, q1);
-
1840  ind10 = flipBit(ind00, q2);
-
1841  ind11 = flipBit(ind01, q2);
-
1842 
-
1843  // extract statevec amplitudes
-
1844  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1845  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1846  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1847  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1848 
-
1849  // apply u * {amp00, amp01, amp10, amp11}
-
1850  reVec[ind00] =
-
1851  u.real[0][0]*re00 - u.imag[0][0]*im00 +
-
1852  u.real[0][1]*re01 - u.imag[0][1]*im01 +
-
1853  u.real[0][2]*re10 - u.imag[0][2]*im10 +
-
1854  u.real[0][3]*re11 - u.imag[0][3]*im11;
-
1855  imVec[ind00] =
-
1856  u.imag[0][0]*re00 + u.real[0][0]*im00 +
-
1857  u.imag[0][1]*re01 + u.real[0][1]*im01 +
-
1858  u.imag[0][2]*re10 + u.real[0][2]*im10 +
-
1859  u.imag[0][3]*re11 + u.real[0][3]*im11;
-
1860 
-
1861  reVec[ind01] =
-
1862  u.real[1][0]*re00 - u.imag[1][0]*im00 +
-
1863  u.real[1][1]*re01 - u.imag[1][1]*im01 +
-
1864  u.real[1][2]*re10 - u.imag[1][2]*im10 +
-
1865  u.real[1][3]*re11 - u.imag[1][3]*im11;
-
1866  imVec[ind01] =
-
1867  u.imag[1][0]*re00 + u.real[1][0]*im00 +
-
1868  u.imag[1][1]*re01 + u.real[1][1]*im01 +
-
1869  u.imag[1][2]*re10 + u.real[1][2]*im10 +
-
1870  u.imag[1][3]*re11 + u.real[1][3]*im11;
+
1786  thisBlock = thisTask / sizeHalfBlock;
+
1787  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1788  indexLo = indexUp + sizeHalfBlock;
+
1789 
+
1790  // store current state vector values in temp variables
+
1791  stateRealUp = stateVecReal[indexUp];
+
1792  stateImagUp = stateVecImag[indexUp];
+
1793 
+
1794  stateRealLo = stateVecReal[indexLo];
+
1795  stateImagLo = stateVecImag[indexLo];
+
1796 
+
1797  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
1798  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
1799  - betaReal*stateRealLo - betaImag*stateImagLo;
+
1800  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
1801  - betaReal*stateImagLo + betaImag*stateRealLo;
+
1802 
+
1803  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
1804  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
1805  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
1806  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
1807  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
1808  }
+
1809  }
+
1810 
+
1811 }
+
1812 
+
1813 void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) {
+
1814 
+
1815  // can't use qureg.stateVec as a private OMP var
+
1816  qreal *reVec = qureg.stateVec.real;
+
1817  qreal *imVec = qureg.stateVec.imag;
+
1818 
+
1819  // the global (between all nodes) index of this node's start index
+
1820  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
+
1821 
+
1822  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
+
1823  long long int thisTask;
+
1824  long long int thisGlobalInd00;
+
1825  long long int ind00, ind01, ind10, ind11;
+
1826  qreal re00, re01, re10, re11;
+
1827  qreal im00, im01, im10, im11;
+
1828 
+
1829 # ifdef _OPENMP
+
1830 # pragma omp parallel \
+
1831  default (none) \
+
1832  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
+
1833  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
+
1834 # endif
+
1835  {
+
1836 # ifdef _OPENMP
+
1837 # pragma omp for schedule (static)
+
1838 # endif
+
1839  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
1840 
+
1841  // determine ind00 of |..0..0..>
+
1842  ind00 = insertTwoZeroBits(thisTask, q1, q2);
+
1843 
+
1844  // skip amplitude if controls aren't in 1 state (overloaded for speed)
+
1845  thisGlobalInd00 = ind00 + globalIndStart;
+
1846  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
+
1847  continue;
+
1848 
+
1849  // inds of |..0..1..>, |..1..0..> and |..1..1..>
+
1850  ind01 = flipBit(ind00, q1);
+
1851  ind10 = flipBit(ind00, q2);
+
1852  ind11 = flipBit(ind01, q2);
+
1853 
+
1854  // extract statevec amplitudes
+
1855  re00 = reVec[ind00]; im00 = imVec[ind00];
+
1856  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1857  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1858  re11 = reVec[ind11]; im11 = imVec[ind11];
+
1859 
+
1860  // apply u * {amp00, amp01, amp10, amp11}
+
1861  reVec[ind00] =
+
1862  u.real[0][0]*re00 - u.imag[0][0]*im00 +
+
1863  u.real[0][1]*re01 - u.imag[0][1]*im01 +
+
1864  u.real[0][2]*re10 - u.imag[0][2]*im10 +
+
1865  u.real[0][3]*re11 - u.imag[0][3]*im11;
+
1866  imVec[ind00] =
+
1867  u.imag[0][0]*re00 + u.real[0][0]*im00 +
+
1868  u.imag[0][1]*re01 + u.real[0][1]*im01 +
+
1869  u.imag[0][2]*re10 + u.real[0][2]*im10 +
+
1870  u.imag[0][3]*re11 + u.real[0][3]*im11;
1871 
-
1872  reVec[ind10] =
-
1873  u.real[2][0]*re00 - u.imag[2][0]*im00 +
-
1874  u.real[2][1]*re01 - u.imag[2][1]*im01 +
-
1875  u.real[2][2]*re10 - u.imag[2][2]*im10 +
-
1876  u.real[2][3]*re11 - u.imag[2][3]*im11;
-
1877  imVec[ind10] =
-
1878  u.imag[2][0]*re00 + u.real[2][0]*im00 +
-
1879  u.imag[2][1]*re01 + u.real[2][1]*im01 +
-
1880  u.imag[2][2]*re10 + u.real[2][2]*im10 +
-
1881  u.imag[2][3]*re11 + u.real[2][3]*im11;
+
1872  reVec[ind01] =
+
1873  u.real[1][0]*re00 - u.imag[1][0]*im00 +
+
1874  u.real[1][1]*re01 - u.imag[1][1]*im01 +
+
1875  u.real[1][2]*re10 - u.imag[1][2]*im10 +
+
1876  u.real[1][3]*re11 - u.imag[1][3]*im11;
+
1877  imVec[ind01] =
+
1878  u.imag[1][0]*re00 + u.real[1][0]*im00 +
+
1879  u.imag[1][1]*re01 + u.real[1][1]*im01 +
+
1880  u.imag[1][2]*re10 + u.real[1][2]*im10 +
+
1881  u.imag[1][3]*re11 + u.real[1][3]*im11;
1882 
-
1883  reVec[ind11] =
-
1884  u.real[3][0]*re00 - u.imag[3][0]*im00 +
-
1885  u.real[3][1]*re01 - u.imag[3][1]*im01 +
-
1886  u.real[3][2]*re10 - u.imag[3][2]*im10 +
-
1887  u.real[3][3]*re11 - u.imag[3][3]*im11;
-
1888  imVec[ind11] =
-
1889  u.imag[3][0]*re00 + u.real[3][0]*im00 +
-
1890  u.imag[3][1]*re01 + u.real[3][1]*im01 +
-
1891  u.imag[3][2]*re10 + u.real[3][2]*im10 +
-
1892  u.imag[3][3]*re11 + u.real[3][3]*im11;
-
1893  }
-
1894  }
-
1895 }
-
1896 
-
1897 int qsortComp(const void *a, const void *b) {
-
1898  return *(int*)a - *(int*)b;
-
1899 }
-
1900 
-
1901 void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
-
1902 {
-
1903  // can't use qureg.stateVec as a private OMP var
-
1904  qreal *reVec = qureg.stateVec.real;
-
1905  qreal *imVec = qureg.stateVec.imag;
-
1906 
-
1907  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
1908  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
-
1909 
-
1910  // the global (between all nodes) index of this node's start index
-
1911  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1912 
-
1913  long long int thisTask;
-
1914  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
-
1915  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
-
1916  long long int ind; // each thread's iteration of amplitudes to modify
-
1917  int i, t, r, c; // each thread's iteration of amps and targets
-
1918  qreal reElem, imElem; // each thread's iteration of u elements
-
1919 
-
1920  // each thread/task will record and modify numTargAmps amplitudes, privately
-
1921  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
-
1922  long long int ampInds[numTargAmps];
-
1923  qreal reAmps[numTargAmps];
-
1924  qreal imAmps[numTargAmps];
-
1925 
-
1926  // we need a sorted targets list to find thisInd00 for each task.
-
1927  // we can't modify targets, because the user-ordering of targets matters in u
-
1928  int sortedTargs[numTargs];
-
1929  for (int t=0; t < numTargs; t++)
-
1930  sortedTargs[t] = targs[t];
-
1931  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
-
1932 
-
1933 # ifdef _OPENMP
-
1934 # pragma omp parallel \
-
1935  default (none) \
-
1936  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
-
1937  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
-
1938 # endif
-
1939  {
-
1940 # ifdef _OPENMP
-
1941 # pragma omp for schedule (static)
-
1942 # endif
-
1943  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1944 
-
1945  // find this task's start index (where all targs are 0)
-
1946  thisInd00 = thisTask;
-
1947  for (t=0; t < numTargs; t++)
-
1948  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
-
1949 
-
1950  // this task only modifies amplitudes if control qubits are 1 for this state
-
1951  thisGlobalInd00 = thisInd00 + globalIndStart;
-
1952  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1953  continue;
-
1954 
-
1955  // determine the indices and record values of this tasks's target amps
-
1956  for (i=0; i < numTargAmps; i++) {
-
1957 
-
1958  // get statevec index of current target qubit assignment
-
1959  ind = thisInd00;
-
1960  for (t=0; t < numTargs; t++)
-
1961  if (extractBit(t, i))
-
1962  ind = flipBit(ind, targs[t]);
-
1963 
-
1964  // update this tasks's private arrays
-
1965  ampInds[i] = ind;
-
1966  reAmps [i] = reVec[ind];
-
1967  imAmps [i] = imVec[ind];
-
1968  }
-
1969 
-
1970  // modify this tasks's target amplitudes
-
1971  for (r=0; r < numTargAmps; r++) {
-
1972  ind = ampInds[r];
-
1973  reVec[ind] = 0;
-
1974  imVec[ind] = 0;
-
1975 
-
1976  for (c=0; c < numTargAmps; c++) {
-
1977  reElem = u.real[r][c];
-
1978  imElem = u.imag[r][c];
-
1979  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
-
1980  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
-
1981  }
-
1982  }
-
1983  }
-
1984  }
-
1985 }
-
1986 
-
1987 void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
1988 {
-
1989  long long int sizeBlock, sizeHalfBlock;
-
1990  long long int thisBlock, // current block
-
1991  indexUp,indexLo; // current index and corresponding index in lower half block
-
1992 
-
1993  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1994  long long int thisTask;
-
1995  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1996 
-
1997  // set dimensions
-
1998  sizeHalfBlock = 1LL << targetQubit;
-
1999  sizeBlock = 2LL * sizeHalfBlock;
-
2000 
-
2001  // Can't use qureg.stateVec as a private OMP var
-
2002  qreal *stateVecReal = qureg.stateVec.real;
-
2003  qreal *stateVecImag = qureg.stateVec.imag;
-
2004 
-
2005 # ifdef _OPENMP
-
2006 # pragma omp parallel \
-
2007  default (none) \
-
2008  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
-
2009  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2010 # endif
-
2011  {
-
2012 # ifdef _OPENMP
-
2013 # pragma omp for schedule (static)
-
2014 # endif
-
2015  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2016 
-
2017  thisBlock = thisTask / sizeHalfBlock;
-
2018  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2019  indexLo = indexUp + sizeHalfBlock;
+
1883  reVec[ind10] =
+
1884  u.real[2][0]*re00 - u.imag[2][0]*im00 +
+
1885  u.real[2][1]*re01 - u.imag[2][1]*im01 +
+
1886  u.real[2][2]*re10 - u.imag[2][2]*im10 +
+
1887  u.real[2][3]*re11 - u.imag[2][3]*im11;
+
1888  imVec[ind10] =
+
1889  u.imag[2][0]*re00 + u.real[2][0]*im00 +
+
1890  u.imag[2][1]*re01 + u.real[2][1]*im01 +
+
1891  u.imag[2][2]*re10 + u.real[2][2]*im10 +
+
1892  u.imag[2][3]*re11 + u.real[2][3]*im11;
+
1893 
+
1894  reVec[ind11] =
+
1895  u.real[3][0]*re00 - u.imag[3][0]*im00 +
+
1896  u.real[3][1]*re01 - u.imag[3][1]*im01 +
+
1897  u.real[3][2]*re10 - u.imag[3][2]*im10 +
+
1898  u.real[3][3]*re11 - u.imag[3][3]*im11;
+
1899  imVec[ind11] =
+
1900  u.imag[3][0]*re00 + u.real[3][0]*im00 +
+
1901  u.imag[3][1]*re01 + u.real[3][1]*im01 +
+
1902  u.imag[3][2]*re10 + u.real[3][2]*im10 +
+
1903  u.imag[3][3]*re11 + u.real[3][3]*im11;
+
1904  }
+
1905  }
+
1906 }
+
1907 
+
1908 int qsortComp(const void *a, const void *b) {
+
1909  return *(int*)a - *(int*)b;
+
1910 }
+
1911 
+
1912 void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
+
1913 {
+
1914  // can't use qureg.stateVec as a private OMP var
+
1915  qreal *reVec = qureg.stateVec.real;
+
1916  qreal *imVec = qureg.stateVec.imag;
+
1917 
+
1918  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
+
1919  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
+
1920 
+
1921  // the global (between all nodes) index of this node's start index
+
1922  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
+
1923 
+
1924  long long int thisTask;
+
1925  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
+
1926  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
+
1927  long long int ind; // each thread's iteration of amplitudes to modify
+
1928  int i, t, r, c; // each thread's iteration of amps and targets
+
1929  qreal reElem, imElem; // each thread's iteration of u elements
+
1930 
+
1931  // each thread/task will record and modify numTargAmps amplitudes, privately
+
1932  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
+
1933  //
+
1934  // If we're NOT on windows, we can fortunately use the stack directly
+
1935  #ifndef _WIN32
+
1936  long long int ampInds[numTargAmps];
+
1937  qreal reAmps[numTargAmps];
+
1938  qreal imAmps[numTargAmps];
+
1939 
+
1940  int sortedTargs[numTargs];
+
1941  // on Windows, with no VLA, we can use _malloca to allocate on stack (must free)
+
1942  #else
+
1943  long long int* ampInds;
+
1944  qreal* reAmps;
+
1945  qreal* imAmps;
+
1946  int* sortedTargs = (int*) _malloca(numTargs * sizeof *sortedTargs);
+
1947  #endif
+
1948 
+
1949  // we need a sorted targets list to find thisInd00 for each task.
+
1950  // we can't modify targets, because the user-ordering of targets matters in u
+
1951  for (int t=0; t < numTargs; t++)
+
1952  sortedTargs[t] = targs[t];
+
1953  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
+
1954 
+
1955 # ifdef _OPENMP
+
1956 # pragma omp parallel \
+
1957  default (none) \
+
1958  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
+
1959  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
+
1960 # endif
+
1961  {
+
1962  // when manually allocating array memory (on Windows), this must be done in each thread
+
1963  // separately and is not performed automatically by declaring a var as omp-private
+
1964  # ifdef _WIN32
+
1965  ampInds = (long long int*) _malloca(numTargAmps * sizeof *ampInds);
+
1966  reAmps = (qreal*) _malloca(numTargAmps * sizeof *reAmps);
+
1967  imAmps = (qreal*) _malloca(numTargAmps * sizeof *imAmps);
+
1968  # endif
+
1969 # ifdef _OPENMP
+
1970 # pragma omp for schedule (static)
+
1971 # endif
+
1972  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
1973 
+
1974  // find this task's start index (where all targs are 0)
+
1975  thisInd00 = thisTask;
+
1976  for (t=0; t < numTargs; t++)
+
1977  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
+
1978 
+
1979  // this task only modifies amplitudes if control qubits are 1 for this state
+
1980  thisGlobalInd00 = thisInd00 + globalIndStart;
+
1981  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
+
1982  continue;
+
1983 
+
1984  // determine the indices and record values of this tasks's target amps
+
1985  for (i=0; i < numTargAmps; i++) {
+
1986 
+
1987  // get statevec index of current target qubit assignment
+
1988  ind = thisInd00;
+
1989  for (t=0; t < numTargs; t++)
+
1990  if (extractBit(t, i))
+
1991  ind = flipBit(ind, targs[t]);
+
1992 
+
1993  // update this tasks's private arrays
+
1994  ampInds[i] = ind;
+
1995  reAmps [i] = reVec[ind];
+
1996  imAmps [i] = imVec[ind];
+
1997  }
+
1998 
+
1999  // modify this tasks's target amplitudes
+
2000  for (r=0; r < numTargAmps; r++) {
+
2001  ind = ampInds[r];
+
2002  reVec[ind] = 0;
+
2003  imVec[ind] = 0;
+
2004 
+
2005  for (c=0; c < numTargAmps; c++) {
+
2006  reElem = u.real[r][c];
+
2007  imElem = u.imag[r][c];
+
2008  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
+
2009  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
+
2010  }
+
2011  }
+
2012  }
+
2013  // on Windows, we must explicitly free the stack structures
+
2014  #ifdef _WIN32
+
2015  _freea(ampInds);
+
2016  _freea(reAmps);
+
2017  _freea(imAmps);
+
2018  #endif
+
2019  }
2020 
-
2021  // store current state vector values in temp variables
-
2022  stateRealUp = stateVecReal[indexUp];
-
2023  stateImagUp = stateVecImag[indexUp];
-
2024 
-
2025  stateRealLo = stateVecReal[indexLo];
-
2026  stateImagLo = stateVecImag[indexLo];
-
2027 
-
2028 
-
2029  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2030  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2031  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2032  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2033  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2034 
-
2035  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2036  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2037  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2038  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2039  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2040 
-
2041  }
-
2042  }
-
2043 }
-
2044 
- -
2057  Complex rot1, Complex rot2,
-
2058  ComplexArray stateVecUp,
-
2059  ComplexArray stateVecLo,
-
2060  ComplexArray stateVecOut)
-
2061 {
-
2062 
-
2063  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2064  long long int thisTask;
-
2065  long long int numTasks=qureg.numAmpsPerChunk;
+
2021  #ifdef _WIN32
+
2022  _freea(sortedTargs);
+
2023  #endif
+
2024 }
+
2025 
+
2026 void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
2027 {
+
2028  long long int sizeBlock, sizeHalfBlock;
+
2029  long long int thisBlock, // current block
+
2030  indexUp,indexLo; // current index and corresponding index in lower half block
+
2031 
+
2032  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2033  long long int thisTask;
+
2034  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2035 
+
2036  // set dimensions
+
2037  sizeHalfBlock = 1LL << targetQubit;
+
2038  sizeBlock = 2LL * sizeHalfBlock;
+
2039 
+
2040  // Can't use qureg.stateVec as a private OMP var
+
2041  qreal *stateVecReal = qureg.stateVec.real;
+
2042  qreal *stateVecImag = qureg.stateVec.imag;
+
2043 
+
2044 # ifdef _OPENMP
+
2045 # pragma omp parallel \
+
2046  default (none) \
+
2047  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
+
2048  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2049 # endif
+
2050  {
+
2051 # ifdef _OPENMP
+
2052 # pragma omp for schedule (static)
+
2053 # endif
+
2054  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2055 
+
2056  thisBlock = thisTask / sizeHalfBlock;
+
2057  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2058  indexLo = indexUp + sizeHalfBlock;
+
2059 
+
2060  // store current state vector values in temp variables
+
2061  stateRealUp = stateVecReal[indexUp];
+
2062  stateImagUp = stateVecImag[indexUp];
+
2063 
+
2064  stateRealLo = stateVecReal[indexLo];
+
2065  stateImagLo = stateVecImag[indexLo];
2066 
-
2067  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2068  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2069  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2070  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2071  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2072 
-
2073 # ifdef _OPENMP
-
2074 # pragma omp parallel \
-
2075  default (none) \
-
2076  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2077  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
-
2078  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2079 # endif
-
2080  {
-
2081 # ifdef _OPENMP
-
2082 # pragma omp for schedule (static)
-
2083 # endif
-
2084  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2085  // store current state vector values in temp variables
-
2086  stateRealUp = stateVecRealUp[thisTask];
-
2087  stateImagUp = stateVecImagUp[thisTask];
-
2088 
-
2089  stateRealLo = stateVecRealLo[thisTask];
-
2090  stateImagLo = stateVecImagLo[thisTask];
-
2091 
-
2092  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2093  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2094  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2095  }
-
2096  }
-
2097 }
-
2098 
- -
2113  Complex rot1, Complex rot2,
-
2114  ComplexArray stateVecUp,
-
2115  ComplexArray stateVecLo,
-
2116  ComplexArray stateVecOut)
-
2117 {
-
2118 
-
2119  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2120  long long int thisTask;
-
2121  long long int numTasks=qureg.numAmpsPerChunk;
-
2122 
-
2123  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2124  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2125  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2126  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2127  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2128 
-
2129 
-
2130 # ifdef _OPENMP
-
2131 # pragma omp parallel \
-
2132  default (none) \
-
2133  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2134  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
-
2135  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2136 # endif
-
2137  {
-
2138 # ifdef _OPENMP
-
2139 # pragma omp for schedule (static)
-
2140 # endif
-
2141  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2142  // store current state vector values in temp variables
-
2143  stateRealUp = stateVecRealUp[thisTask];
-
2144  stateImagUp = stateVecImagUp[thisTask];
-
2145 
-
2146  stateRealLo = stateVecRealLo[thisTask];
-
2147  stateImagLo = stateVecImagLo[thisTask];
-
2148 
-
2149  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2150  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2151  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2152  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2153  }
-
2154  }
-
2155 }
-
2156 
-
2157 void statevec_controlledCompactUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit,
-
2158  Complex alpha, Complex beta)
-
2159 {
-
2160  long long int sizeBlock, sizeHalfBlock;
-
2161  long long int thisBlock, // current block
-
2162  indexUp,indexLo; // current index and corresponding index in lower half block
-
2163 
-
2164  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2165  long long int thisTask;
-
2166  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2167  long long int chunkSize=qureg.numAmpsPerChunk;
-
2168  long long int chunkId=qureg.chunkId;
-
2169 
-
2170  int controlBit;
-
2171 
-
2172  // set dimensions
-
2173  sizeHalfBlock = 1LL << targetQubit;
-
2174  sizeBlock = 2LL * sizeHalfBlock;
-
2175 
-
2176  // Can't use qureg.stateVec as a private OMP var
-
2177  qreal *stateVecReal = qureg.stateVec.real;
-
2178  qreal *stateVecImag = qureg.stateVec.imag;
-
2179  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
2180  qreal betaImag=beta.imag, betaReal=beta.real;
-
2181 
-
2182 # ifdef _OPENMP
-
2183 # pragma omp parallel \
-
2184  default (none) \
-
2185  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
-
2186  numTasks,chunkId,chunkSize,controlQubit) \
-
2187  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2188 # endif
-
2189  {
-
2190 # ifdef _OPENMP
-
2191 # pragma omp for schedule (static)
-
2192 # endif
-
2193  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2194 
-
2195  thisBlock = thisTask / sizeHalfBlock;
-
2196  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2197  indexLo = indexUp + sizeHalfBlock;
-
2198 
-
2199  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2200  if (controlBit){
-
2201  // store current state vector values in temp variables
-
2202  stateRealUp = stateVecReal[indexUp];
-
2203  stateImagUp = stateVecImag[indexUp];
-
2204 
-
2205  stateRealLo = stateVecReal[indexLo];
-
2206  stateImagLo = stateVecImag[indexLo];
-
2207 
-
2208  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2209  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
2210  - betaReal*stateRealLo - betaImag*stateImagLo;
-
2211  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
2212  - betaReal*stateImagLo + betaImag*stateRealLo;
-
2213 
-
2214  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
2215  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
2216  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
2217  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
2218  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
2219  }
-
2220  }
-
2221  }
-
2222 
-
2223 }
-
2224 
-
2225 /* ctrlQubitsMask is a bit mask indicating which qubits are control Qubits
-
2226  * ctrlFlipMask is a bit mask indicating which control qubits should be 'flipped'
-
2227  * in the condition, i.e. they should have value 0 when the unitary is applied
-
2228  */
- -
2230  Qureg qureg, int targetQubit,
-
2231  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
2232  ComplexMatrix2 u)
-
2233 {
-
2234  long long int sizeBlock, sizeHalfBlock;
-
2235  long long int thisBlock, // current block
-
2236  indexUp,indexLo; // current index and corresponding index in lower half block
+
2067 
+
2068  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2069  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2070  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2071  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2072  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2073 
+
2074  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2075  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2076  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2077  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2078  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2079 
+
2080  }
+
2081  }
+
2082 }
+
2083 
+ +
2096  Complex rot1, Complex rot2,
+
2097  ComplexArray stateVecUp,
+
2098  ComplexArray stateVecLo,
+
2099  ComplexArray stateVecOut)
+
2100 {
+
2101 
+
2102  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2103  long long int thisTask;
+
2104  long long int numTasks=qureg.numAmpsPerChunk;
+
2105 
+
2106  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2107  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2108  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2109  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2110  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2111 
+
2112 # ifdef _OPENMP
+
2113 # pragma omp parallel \
+
2114  default (none) \
+
2115  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2116  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
+
2117  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2118 # endif
+
2119  {
+
2120 # ifdef _OPENMP
+
2121 # pragma omp for schedule (static)
+
2122 # endif
+
2123  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2124  // store current state vector values in temp variables
+
2125  stateRealUp = stateVecRealUp[thisTask];
+
2126  stateImagUp = stateVecImagUp[thisTask];
+
2127 
+
2128  stateRealLo = stateVecRealLo[thisTask];
+
2129  stateImagLo = stateVecImagLo[thisTask];
+
2130 
+
2131  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2132  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
+
2133  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
+
2134  }
+
2135  }
+
2136 }
+
2137 
+ +
2152  Complex rot1, Complex rot2,
+
2153  ComplexArray stateVecUp,
+
2154  ComplexArray stateVecLo,
+
2155  ComplexArray stateVecOut)
+
2156 {
+
2157 
+
2158  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2159  long long int thisTask;
+
2160  long long int numTasks=qureg.numAmpsPerChunk;
+
2161 
+
2162  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2163  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2164  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2165  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2166  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2167 
+
2168 
+
2169 # ifdef _OPENMP
+
2170 # pragma omp parallel \
+
2171  default (none) \
+
2172  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2173  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
+
2174  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2175 # endif
+
2176  {
+
2177 # ifdef _OPENMP
+
2178 # pragma omp for schedule (static)
+
2179 # endif
+
2180  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2181  // store current state vector values in temp variables
+
2182  stateRealUp = stateVecRealUp[thisTask];
+
2183  stateImagUp = stateVecImagUp[thisTask];
+
2184 
+
2185  stateRealLo = stateVecRealLo[thisTask];
+
2186  stateImagLo = stateVecImagLo[thisTask];
+
2187 
+
2188  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2189  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2190  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2191  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2192  }
+
2193  }
+
2194 }
+
2195 
+
2196 void statevec_controlledCompactUnitaryLocal (Qureg qureg, int controlQubit, int targetQubit,
+
2197  Complex alpha, Complex beta)
+
2198 {
+
2199  long long int sizeBlock, sizeHalfBlock;
+
2200  long long int thisBlock, // current block
+
2201  indexUp,indexLo; // current index and corresponding index in lower half block
+
2202 
+
2203  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2204  long long int thisTask;
+
2205  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2206  long long int chunkSize=qureg.numAmpsPerChunk;
+
2207  long long int chunkId=qureg.chunkId;
+
2208 
+
2209  int controlBit;
+
2210 
+
2211  // set dimensions
+
2212  sizeHalfBlock = 1LL << targetQubit;
+
2213  sizeBlock = 2LL * sizeHalfBlock;
+
2214 
+
2215  // Can't use qureg.stateVec as a private OMP var
+
2216  qreal *stateVecReal = qureg.stateVec.real;
+
2217  qreal *stateVecImag = qureg.stateVec.imag;
+
2218  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
2219  qreal betaImag=beta.imag, betaReal=beta.real;
+
2220 
+
2221 # ifdef _OPENMP
+
2222 # pragma omp parallel \
+
2223  default (none) \
+
2224  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
+
2225  numTasks,chunkId,chunkSize,controlQubit) \
+
2226  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2227 # endif
+
2228  {
+
2229 # ifdef _OPENMP
+
2230 # pragma omp for schedule (static)
+
2231 # endif
+
2232  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2233 
+
2234  thisBlock = thisTask / sizeHalfBlock;
+
2235  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2236  indexLo = indexUp + sizeHalfBlock;
2237 
-
2238  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2239  long long int thisTask;
-
2240  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2241  long long int chunkSize=qureg.numAmpsPerChunk;
-
2242  long long int chunkId=qureg.chunkId;
+
2238  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
+
2239  if (controlBit){
+
2240  // store current state vector values in temp variables
+
2241  stateRealUp = stateVecReal[indexUp];
+
2242  stateImagUp = stateVecImag[indexUp];
2243 
-
2244  // set dimensions
-
2245  sizeHalfBlock = 1LL << targetQubit;
-
2246  sizeBlock = 2LL * sizeHalfBlock;
-
2247 
-
2248  // Can't use qureg.stateVec as a private OMP var
-
2249  qreal *stateVecReal = qureg.stateVec.real;
-
2250  qreal *stateVecImag = qureg.stateVec.imag;
-
2251 
-
2252 # ifdef _OPENMP
-
2253 # pragma omp parallel \
-
2254  default (none) \
-
2255  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
-
2256  numTasks,chunkId,chunkSize) \
-
2257  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2258 # endif
-
2259  {
-
2260 # ifdef _OPENMP
-
2261 # pragma omp for schedule (static)
-
2262 # endif
-
2263  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2264 
-
2265  thisBlock = thisTask / sizeHalfBlock;
-
2266  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2267  indexLo = indexUp + sizeHalfBlock;
-
2268 
-
2269 
-
2270  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
-
2271  // if this equals the control mask, the control qubits have the desired values in the basis index
-
2272  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2273  // store current state vector values in temp variables
-
2274  stateRealUp = stateVecReal[indexUp];
-
2275  stateImagUp = stateVecImag[indexUp];
+
2244  stateRealLo = stateVecReal[indexLo];
+
2245  stateImagLo = stateVecImag[indexLo];
+
2246 
+
2247  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2248  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
2249  - betaReal*stateRealLo - betaImag*stateImagLo;
+
2250  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
2251  - betaReal*stateImagLo + betaImag*stateRealLo;
+
2252 
+
2253  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
2254  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
2255  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
2256  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
2257  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
2258  }
+
2259  }
+
2260  }
+
2261 
+
2262 }
+
2263 
+
2264 /* ctrlQubitsMask is a bit mask indicating which qubits are control Qubits
+
2265  * ctrlFlipMask is a bit mask indicating which control qubits should be 'flipped'
+
2266  * in the condition, i.e. they should have value 0 when the unitary is applied
+
2267  */
+ +
2269  Qureg qureg, int targetQubit,
+
2270  long long int ctrlQubitsMask, long long int ctrlFlipMask,
+
2271  ComplexMatrix2 u)
+
2272 {
+
2273  long long int sizeBlock, sizeHalfBlock;
+
2274  long long int thisBlock, // current block
+
2275  indexUp,indexLo; // current index and corresponding index in lower half block
2276 
-
2277  stateRealLo = stateVecReal[indexLo];
-
2278  stateImagLo = stateVecImag[indexLo];
-
2279 
-
2280  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2281  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2282  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2283  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2284  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2285 
-
2286  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2287  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2288  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2289  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2290  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2291  }
-
2292  }
-
2293  }
-
2294 
-
2295 }
-
2296 
-
2297 void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit,
-
2298  ComplexMatrix2 u)
-
2299 {
-
2300  long long int sizeBlock, sizeHalfBlock;
-
2301  long long int thisBlock, // current block
-
2302  indexUp,indexLo; // current index and corresponding index in lower half block
+
2277  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2278  long long int thisTask;
+
2279  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2280  long long int chunkSize=qureg.numAmpsPerChunk;
+
2281  long long int chunkId=qureg.chunkId;
+
2282 
+
2283  // set dimensions
+
2284  sizeHalfBlock = 1LL << targetQubit;
+
2285  sizeBlock = 2LL * sizeHalfBlock;
+
2286 
+
2287  // Can't use qureg.stateVec as a private OMP var
+
2288  qreal *stateVecReal = qureg.stateVec.real;
+
2289  qreal *stateVecImag = qureg.stateVec.imag;
+
2290 
+
2291 # ifdef _OPENMP
+
2292 # pragma omp parallel \
+
2293  default (none) \
+
2294  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
+
2295  numTasks,chunkId,chunkSize) \
+
2296  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2297 # endif
+
2298  {
+
2299 # ifdef _OPENMP
+
2300 # pragma omp for schedule (static)
+
2301 # endif
+
2302  for (thisTask=0; thisTask<numTasks; thisTask++) {
2303 
-
2304  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2305  long long int thisTask;
-
2306  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2307  long long int chunkSize=qureg.numAmpsPerChunk;
-
2308  long long int chunkId=qureg.chunkId;
-
2309 
-
2310  int controlBit;
-
2311 
-
2312  // set dimensions
-
2313  sizeHalfBlock = 1LL << targetQubit;
-
2314  sizeBlock = 2LL * sizeHalfBlock;
+
2304  thisBlock = thisTask / sizeHalfBlock;
+
2305  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2306  indexLo = indexUp + sizeHalfBlock;
+
2307 
+
2308 
+
2309  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
+
2310  // if this equals the control mask, the control qubits have the desired values in the basis index
+
2311  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
+
2312  // store current state vector values in temp variables
+
2313  stateRealUp = stateVecReal[indexUp];
+
2314  stateImagUp = stateVecImag[indexUp];
2315 
-
2316  // Can't use qureg.stateVec as a private OMP var
-
2317  qreal *stateVecReal = qureg.stateVec.real;
-
2318  qreal *stateVecImag = qureg.stateVec.imag;
-
2319 
-
2320 # ifdef _OPENMP
-
2321 # pragma omp parallel \
-
2322  default (none) \
-
2323  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
-
2324  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2325 # endif
-
2326  {
-
2327 # ifdef _OPENMP
-
2328 # pragma omp for schedule (static)
-
2329 # endif
-
2330  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2331 
-
2332  thisBlock = thisTask / sizeHalfBlock;
-
2333  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2334  indexLo = indexUp + sizeHalfBlock;
+
2316  stateRealLo = stateVecReal[indexLo];
+
2317  stateImagLo = stateVecImag[indexLo];
+
2318 
+
2319  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2320  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2321  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2322  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2323  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2324 
+
2325  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2326  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2327  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2328  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2329  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2330  }
+
2331  }
+
2332  }
+
2333 
+
2334 }
2335 
-
2336  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2337  if (controlBit){
-
2338  // store current state vector values in temp variables
-
2339  stateRealUp = stateVecReal[indexUp];
-
2340  stateImagUp = stateVecImag[indexUp];
-
2341 
-
2342  stateRealLo = stateVecReal[indexLo];
-
2343  stateImagLo = stateVecImag[indexLo];
-
2344 
-
2345 
-
2346  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2347  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2348  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2349  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2350  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2351 
-
2352  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2353  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2354  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2355  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2356  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2357  }
-
2358  }
-
2359  }
-
2360 
-
2361 }
-
2362 
- -
2376  Complex rot1, Complex rot2,
-
2377  ComplexArray stateVecUp,
-
2378  ComplexArray stateVecLo,
-
2379  ComplexArray stateVecOut)
-
2380 {
-
2381 
-
2382  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2383  long long int thisTask;
-
2384  long long int numTasks=qureg.numAmpsPerChunk;
-
2385  long long int chunkSize=qureg.numAmpsPerChunk;
-
2386  long long int chunkId=qureg.chunkId;
-
2387 
-
2388  int controlBit;
-
2389 
-
2390  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2391  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2392  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2393  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2394  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2395 
-
2396 # ifdef _OPENMP
-
2397 # pragma omp parallel \
-
2398  default (none) \
-
2399  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2400  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
-
2401  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2402 # endif
-
2403  {
-
2404 # ifdef _OPENMP
-
2405 # pragma omp for schedule (static)
-
2406 # endif
-
2407  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2408  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2409  if (controlBit){
-
2410  // store current state vector values in temp variables
-
2411  stateRealUp = stateVecRealUp[thisTask];
-
2412  stateImagUp = stateVecImagUp[thisTask];
-
2413 
-
2414  stateRealLo = stateVecRealLo[thisTask];
-
2415  stateImagLo = stateVecImagLo[thisTask];
-
2416 
-
2417  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2418  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2419  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2420  }
-
2421  }
-
2422  }
-
2423 }
-
2424 
-
2437 void statevec_controlledUnitaryDistributed (Qureg qureg, int controlQubit,
-
2438  Complex rot1, Complex rot2,
-
2439  ComplexArray stateVecUp,
-
2440  ComplexArray stateVecLo,
-
2441  ComplexArray stateVecOut)
-
2442 {
-
2443 
-
2444  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2445  long long int thisTask;
-
2446  long long int numTasks=qureg.numAmpsPerChunk;
-
2447  long long int chunkSize=qureg.numAmpsPerChunk;
-
2448  long long int chunkId=qureg.chunkId;
-
2449 
-
2450  int controlBit;
-
2451 
-
2452  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2453  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2454  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2455  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2456  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2457 
-
2458 # ifdef _OPENMP
-
2459 # pragma omp parallel \
-
2460  default (none) \
-
2461  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2462  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
-
2463  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2464 # endif
-
2465  {
-
2466 # ifdef _OPENMP
-
2467 # pragma omp for schedule (static)
-
2468 # endif
-
2469  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2470  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2471  if (controlBit){
-
2472  // store current state vector values in temp variables
-
2473  stateRealUp = stateVecRealUp[thisTask];
-
2474  stateImagUp = stateVecImagUp[thisTask];
-
2475 
-
2476  stateRealLo = stateVecRealLo[thisTask];
-
2477  stateImagLo = stateVecImagLo[thisTask];
-
2478 
-
2479  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2480  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2481  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2482  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2483  }
-
2484  }
-
2485  }
-
2486 }
-
2487 
- -
2504  Qureg qureg,
-
2505  int targetQubit,
-
2506  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
2507  Complex rot1, Complex rot2,
-
2508  ComplexArray stateVecUp,
-
2509  ComplexArray stateVecLo,
-
2510  ComplexArray stateVecOut)
-
2511 {
-
2512 
-
2513  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2514  long long int thisTask;
-
2515  long long int numTasks=qureg.numAmpsPerChunk;
-
2516  long long int chunkSize=qureg.numAmpsPerChunk;
-
2517  long long int chunkId=qureg.chunkId;
-
2518 
-
2519  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2520  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2521  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2522  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2523  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2524 
-
2525 # ifdef _OPENMP
-
2526 # pragma omp parallel \
-
2527  default (none) \
-
2528  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2529  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
-
2530  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2531 # endif
-
2532  {
-
2533 # ifdef _OPENMP
-
2534 # pragma omp for schedule (static)
-
2535 # endif
-
2536  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2537  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2538  // store current state vector values in temp variables
-
2539  stateRealUp = stateVecRealUp[thisTask];
-
2540  stateImagUp = stateVecImagUp[thisTask];
-
2541 
-
2542  stateRealLo = stateVecRealLo[thisTask];
-
2543  stateImagLo = stateVecImagLo[thisTask];
-
2544 
-
2545  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2546  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2547  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2548  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2549  }
-
2550  }
-
2551  }
-
2552 }
-
2553 
-
2554 void statevec_pauliXLocal(Qureg qureg, int targetQubit)
-
2555 {
-
2556  long long int sizeBlock, sizeHalfBlock;
-
2557  long long int thisBlock, // current block
-
2558  indexUp,indexLo; // current index and corresponding index in lower half block
-
2559 
-
2560  qreal stateRealUp,stateImagUp;
-
2561  long long int thisTask;
-
2562  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2336 void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit,
+
2337  ComplexMatrix2 u)
+
2338 {
+
2339  long long int sizeBlock, sizeHalfBlock;
+
2340  long long int thisBlock, // current block
+
2341  indexUp,indexLo; // current index and corresponding index in lower half block
+
2342 
+
2343  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2344  long long int thisTask;
+
2345  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2346  long long int chunkSize=qureg.numAmpsPerChunk;
+
2347  long long int chunkId=qureg.chunkId;
+
2348 
+
2349  int controlBit;
+
2350 
+
2351  // set dimensions
+
2352  sizeHalfBlock = 1LL << targetQubit;
+
2353  sizeBlock = 2LL * sizeHalfBlock;
+
2354 
+
2355  // Can't use qureg.stateVec as a private OMP var
+
2356  qreal *stateVecReal = qureg.stateVec.real;
+
2357  qreal *stateVecImag = qureg.stateVec.imag;
+
2358 
+
2359 # ifdef _OPENMP
+
2360 # pragma omp parallel \
+
2361  default (none) \
+
2362  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
+
2363  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2364 # endif
+
2365  {
+
2366 # ifdef _OPENMP
+
2367 # pragma omp for schedule (static)
+
2368 # endif
+
2369  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2370 
+
2371  thisBlock = thisTask / sizeHalfBlock;
+
2372  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2373  indexLo = indexUp + sizeHalfBlock;
+
2374 
+
2375  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
+
2376  if (controlBit){
+
2377  // store current state vector values in temp variables
+
2378  stateRealUp = stateVecReal[indexUp];
+
2379  stateImagUp = stateVecImag[indexUp];
+
2380 
+
2381  stateRealLo = stateVecReal[indexLo];
+
2382  stateImagLo = stateVecImag[indexLo];
+
2383 
+
2384 
+
2385  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2386  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2387  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2388  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2389  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2390 
+
2391  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2392  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2393  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2394  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2395  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2396  }
+
2397  }
+
2398  }
+
2399 
+
2400 }
+
2401 
+ +
2415  Complex rot1, Complex rot2,
+
2416  ComplexArray stateVecUp,
+
2417  ComplexArray stateVecLo,
+
2418  ComplexArray stateVecOut)
+
2419 {
+
2420 
+
2421  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2422  long long int thisTask;
+
2423  long long int numTasks=qureg.numAmpsPerChunk;
+
2424  long long int chunkSize=qureg.numAmpsPerChunk;
+
2425  long long int chunkId=qureg.chunkId;
+
2426 
+
2427  int controlBit;
+
2428 
+
2429  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2430  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2431  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2432  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2433  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2434 
+
2435 # ifdef _OPENMP
+
2436 # pragma omp parallel \
+
2437  default (none) \
+
2438  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2439  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
+
2440  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2441 # endif
+
2442  {
+
2443 # ifdef _OPENMP
+
2444 # pragma omp for schedule (static)
+
2445 # endif
+
2446  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2447  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2448  if (controlBit){
+
2449  // store current state vector values in temp variables
+
2450  stateRealUp = stateVecRealUp[thisTask];
+
2451  stateImagUp = stateVecImagUp[thisTask];
+
2452 
+
2453  stateRealLo = stateVecRealLo[thisTask];
+
2454  stateImagLo = stateVecImagLo[thisTask];
+
2455 
+
2456  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2457  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
+
2458  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
+
2459  }
+
2460  }
+
2461  }
+
2462 }
+
2463 
+
2476 void statevec_controlledUnitaryDistributed (Qureg qureg, int controlQubit,
+
2477  Complex rot1, Complex rot2,
+
2478  ComplexArray stateVecUp,
+
2479  ComplexArray stateVecLo,
+
2480  ComplexArray stateVecOut)
+
2481 {
+
2482 
+
2483  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2484  long long int thisTask;
+
2485  long long int numTasks=qureg.numAmpsPerChunk;
+
2486  long long int chunkSize=qureg.numAmpsPerChunk;
+
2487  long long int chunkId=qureg.chunkId;
+
2488 
+
2489  int controlBit;
+
2490 
+
2491  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2492  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2493  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2494  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2495  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2496 
+
2497 # ifdef _OPENMP
+
2498 # pragma omp parallel \
+
2499  default (none) \
+
2500  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2501  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
+
2502  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2503 # endif
+
2504  {
+
2505 # ifdef _OPENMP
+
2506 # pragma omp for schedule (static)
+
2507 # endif
+
2508  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2509  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2510  if (controlBit){
+
2511  // store current state vector values in temp variables
+
2512  stateRealUp = stateVecRealUp[thisTask];
+
2513  stateImagUp = stateVecImagUp[thisTask];
+
2514 
+
2515  stateRealLo = stateVecRealLo[thisTask];
+
2516  stateImagLo = stateVecImagLo[thisTask];
+
2517 
+
2518  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2519  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2520  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2521  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2522  }
+
2523  }
+
2524  }
+
2525 }
+
2526 
+ +
2543  Qureg qureg,
+
2544  int targetQubit,
+
2545  long long int ctrlQubitsMask, long long int ctrlFlipMask,
+
2546  Complex rot1, Complex rot2,
+
2547  ComplexArray stateVecUp,
+
2548  ComplexArray stateVecLo,
+
2549  ComplexArray stateVecOut)
+
2550 {
+
2551 
+
2552  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2553  long long int thisTask;
+
2554  long long int numTasks=qureg.numAmpsPerChunk;
+
2555  long long int chunkSize=qureg.numAmpsPerChunk;
+
2556  long long int chunkId=qureg.chunkId;
+
2557 
+
2558  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2559  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2560  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2561  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2562  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
2563 
-
2564  // set dimensions
-
2565  sizeHalfBlock = 1LL << targetQubit;
-
2566  sizeBlock = 2LL * sizeHalfBlock;
-
2567 
-
2568  // Can't use qureg.stateVec as a private OMP var
-
2569  qreal *stateVecReal = qureg.stateVec.real;
-
2570  qreal *stateVecImag = qureg.stateVec.imag;
-
2571 
+
2564 # ifdef _OPENMP
+
2565 # pragma omp parallel \
+
2566  default (none) \
+
2567  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2568  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
+
2569  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2570 # endif
+
2571  {
2572 # ifdef _OPENMP
-
2573 # pragma omp parallel \
-
2574  default (none) \
-
2575  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
-
2576  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2577 # endif
-
2578  {
-
2579 # ifdef _OPENMP
-
2580 # pragma omp for schedule (static)
-
2581 # endif
-
2582  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2583  thisBlock = thisTask / sizeHalfBlock;
-
2584  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2585  indexLo = indexUp + sizeHalfBlock;
-
2586 
-
2587  stateRealUp = stateVecReal[indexUp];
-
2588  stateImagUp = stateVecImag[indexUp];
-
2589 
-
2590  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2591  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2573 # pragma omp for schedule (static)
+
2574 # endif
+
2575  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2576  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
+
2577  // store current state vector values in temp variables
+
2578  stateRealUp = stateVecRealUp[thisTask];
+
2579  stateImagUp = stateVecImagUp[thisTask];
+
2580 
+
2581  stateRealLo = stateVecRealLo[thisTask];
+
2582  stateImagLo = stateVecImagLo[thisTask];
+
2583 
+
2584  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2585  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2586  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2587  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2588  }
+
2589  }
+
2590  }
+
2591 }
2592 
-
2593  stateVecReal[indexLo] = stateRealUp;
-
2594  stateVecImag[indexLo] = stateImagUp;
-
2595  }
-
2596  }
-
2597 
-
2598 }
-
2599 
- -
2613  ComplexArray stateVecIn,
-
2614  ComplexArray stateVecOut)
-
2615 {
-
2616 
-
2617  long long int thisTask;
-
2618  long long int numTasks=qureg.numAmpsPerChunk;
-
2619 
-
2620  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2621  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2622 
-
2623 # ifdef _OPENMP
-
2624 # pragma omp parallel \
-
2625  default (none) \
-
2626  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
-
2627  private (thisTask)
-
2628 # endif
-
2629  {
-
2630 # ifdef _OPENMP
-
2631 # pragma omp for schedule (static)
-
2632 # endif
-
2633  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2634  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2635  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2636  }
-
2637  }
-
2638 }
-
2639 
-
2640 void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
-
2641 {
-
2642  long long int sizeBlock, sizeHalfBlock;
-
2643  long long int thisBlock, // current block
-
2644  indexUp,indexLo; // current index and corresponding index in lower half block
-
2645 
-
2646  qreal stateRealUp,stateImagUp;
-
2647  long long int thisTask;
-
2648  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2649  long long int chunkSize=qureg.numAmpsPerChunk;
-
2650  long long int chunkId=qureg.chunkId;
-
2651 
-
2652  int controlBit;
-
2653 
-
2654  // set dimensions
-
2655  sizeHalfBlock = 1LL << targetQubit;
-
2656  sizeBlock = 2LL * sizeHalfBlock;
-
2657 
-
2658  // Can't use qureg.stateVec as a private OMP var
-
2659  qreal *stateVecReal = qureg.stateVec.real;
-
2660  qreal *stateVecImag = qureg.stateVec.imag;
+
2593 void statevec_pauliXLocal(Qureg qureg, int targetQubit)
+
2594 {
+
2595  long long int sizeBlock, sizeHalfBlock;
+
2596  long long int thisBlock, // current block
+
2597  indexUp,indexLo; // current index and corresponding index in lower half block
+
2598 
+
2599  qreal stateRealUp,stateImagUp;
+
2600  long long int thisTask;
+
2601  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2602 
+
2603  // set dimensions
+
2604  sizeHalfBlock = 1LL << targetQubit;
+
2605  sizeBlock = 2LL * sizeHalfBlock;
+
2606 
+
2607  // Can't use qureg.stateVec as a private OMP var
+
2608  qreal *stateVecReal = qureg.stateVec.real;
+
2609  qreal *stateVecImag = qureg.stateVec.imag;
+
2610 
+
2611 # ifdef _OPENMP
+
2612 # pragma omp parallel \
+
2613  default (none) \
+
2614  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
+
2615  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
+
2616 # endif
+
2617  {
+
2618 # ifdef _OPENMP
+
2619 # pragma omp for schedule (static)
+
2620 # endif
+
2621  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2622  thisBlock = thisTask / sizeHalfBlock;
+
2623  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2624  indexLo = indexUp + sizeHalfBlock;
+
2625 
+
2626  stateRealUp = stateVecReal[indexUp];
+
2627  stateImagUp = stateVecImag[indexUp];
+
2628 
+
2629  stateVecReal[indexUp] = stateVecReal[indexLo];
+
2630  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2631 
+
2632  stateVecReal[indexLo] = stateRealUp;
+
2633  stateVecImag[indexLo] = stateImagUp;
+
2634  }
+
2635  }
+
2636 
+
2637 }
+
2638 
+ +
2652  ComplexArray stateVecIn,
+
2653  ComplexArray stateVecOut)
+
2654 {
+
2655 
+
2656  long long int thisTask;
+
2657  long long int numTasks=qureg.numAmpsPerChunk;
+
2658 
+
2659  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2660  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
2661 
2662 # ifdef _OPENMP
2663 # pragma omp parallel \
2664  default (none) \
-
2665  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
-
2666  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
2665  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
+
2666  private (thisTask)
2667 # endif
2668  {
2669 # ifdef _OPENMP
2670 # pragma omp for schedule (static)
2671 # endif
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2673  thisBlock = thisTask / sizeHalfBlock;
-
2674  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2675  indexLo = indexUp + sizeHalfBlock;
-
2676 
-
2677  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2678  if (controlBit){
-
2679  stateRealUp = stateVecReal[indexUp];
-
2680  stateImagUp = stateVecImag[indexUp];
-
2681 
-
2682  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2683  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2673  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
+
2674  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
+
2675  }
+
2676  }
+
2677 }
+
2678 
+
2679 void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
+
2680 {
+
2681  long long int sizeBlock, sizeHalfBlock;
+
2682  long long int thisBlock, // current block
+
2683  indexUp,indexLo; // current index and corresponding index in lower half block
2684 
-
2685  stateVecReal[indexLo] = stateRealUp;
-
2686  stateVecImag[indexLo] = stateImagUp;
-
2687  }
-
2688  }
-
2689  }
-
2690 }
-
2691 
-
2703 void statevec_controlledNotDistributed (Qureg qureg, int controlQubit,
-
2704  ComplexArray stateVecIn,
-
2705  ComplexArray stateVecOut)
-
2706 {
-
2707 
-
2708  long long int thisTask;
-
2709  long long int numTasks=qureg.numAmpsPerChunk;
-
2710  long long int chunkSize=qureg.numAmpsPerChunk;
-
2711  long long int chunkId=qureg.chunkId;
-
2712 
-
2713  int controlBit;
-
2714 
-
2715  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2716  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2717 
-
2718 # ifdef _OPENMP
-
2719 # pragma omp parallel \
-
2720  default (none) \
-
2721  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2722  numTasks,chunkId,chunkSize,controlQubit) \
-
2723  private (thisTask,controlBit)
-
2724 # endif
-
2725  {
-
2726 # ifdef _OPENMP
-
2727 # pragma omp for schedule (static)
-
2728 # endif
-
2729  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2730  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2731  if (controlBit){
-
2732  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2733  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2734  }
-
2735  }
-
2736  }
-
2737 }
-
2738 
-
2739 void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask) {
-
2740  long long int numAmps = qureg.numAmpsPerChunk;
-
2741  qreal* stateRe = qureg.stateVec.real;
-
2742  qreal* stateIm = qureg.stateVec.imag;
-
2743 
-
2744  long long int globalOffset = qureg.chunkId * numAmps;
-
2745 
-
2746  // each amplitude is swapped with a 'mate' amplitude
-
2747  long long int ampInd, mateInd, globalInd;
-
2748  qreal mateRe, mateIm;
-
2749 
-
2750 # ifdef _OPENMP
-
2751 # pragma omp parallel \
-
2752  default (none) \
-
2753  shared (stateRe,stateIm, numAmps, ctrlMask,targMask, globalOffset) \
-
2754  private (ampInd, mateInd,mateRe,mateIm, globalInd)
-
2755 # endif
-
2756  {
+
2685  qreal stateRealUp,stateImagUp;
+
2686  long long int thisTask;
+
2687  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2688  long long int chunkSize=qureg.numAmpsPerChunk;
+
2689  long long int chunkId=qureg.chunkId;
+
2690 
+
2691  int controlBit;
+
2692 
+
2693  // set dimensions
+
2694  sizeHalfBlock = 1LL << targetQubit;
+
2695  sizeBlock = 2LL * sizeHalfBlock;
+
2696 
+
2697  // Can't use qureg.stateVec as a private OMP var
+
2698  qreal *stateVecReal = qureg.stateVec.real;
+
2699  qreal *stateVecImag = qureg.stateVec.imag;
+
2700 
+
2701 # ifdef _OPENMP
+
2702 # pragma omp parallel \
+
2703  default (none) \
+
2704  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
+
2705  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
2706 # endif
+
2707  {
+
2708 # ifdef _OPENMP
+
2709 # pragma omp for schedule (static)
+
2710 # endif
+
2711  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2712  thisBlock = thisTask / sizeHalfBlock;
+
2713  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2714  indexLo = indexUp + sizeHalfBlock;
+
2715 
+
2716  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
+
2717  if (controlBit){
+
2718  stateRealUp = stateVecReal[indexUp];
+
2719  stateImagUp = stateVecImag[indexUp];
+
2720 
+
2721  stateVecReal[indexUp] = stateVecReal[indexLo];
+
2722  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2723 
+
2724  stateVecReal[indexLo] = stateRealUp;
+
2725  stateVecImag[indexLo] = stateImagUp;
+
2726  }
+
2727  }
+
2728  }
+
2729 }
+
2730 
+
2742 void statevec_controlledNotDistributed (Qureg qureg, int controlQubit,
+
2743  ComplexArray stateVecIn,
+
2744  ComplexArray stateVecOut)
+
2745 {
+
2746 
+
2747  long long int thisTask;
+
2748  long long int numTasks=qureg.numAmpsPerChunk;
+
2749  long long int chunkSize=qureg.numAmpsPerChunk;
+
2750  long long int chunkId=qureg.chunkId;
+
2751 
+
2752  int controlBit;
+
2753 
+
2754  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2755  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2756 
2757 # ifdef _OPENMP
-
2758 # pragma omp for schedule (static)
-
2759 # endif
-
2760  for (ampInd = 0; ampInd < numAmps; ampInd++) {
-
2761 
-
2762  /* it may be a premature optimisation to remove the seemingly wasteful continues below,
-
2763  * because the maximum skipped amplitudes is 1/2 that stored in the node
-
2764  * (e.g. since this function is not called if all amps should be skipped via controls),
-
2765  * and since we're memory-bandwidth bottlenecked.
-
2766  */
-
2767 
-
2768  // although amps are local, we may still be running in distributed mode,
-
2769  // and hence need to consult the global index to determine the values of
-
2770  // the control qubits
-
2771  globalInd = ampInd + globalOffset;
-
2772 
-
2773  // modify amplitude only if control qubits are 1 for this state
-
2774  if (ctrlMask && ((ctrlMask & globalInd) != ctrlMask))
-
2775  continue;
-
2776 
-
2777  mateInd = ampInd ^ targMask;
-
2778 
-
2779  // if the mate is behind, it was already processed
-
2780  if (mateInd < ampInd)
-
2781  continue;
-
2782 
-
2783  mateRe = stateRe[mateInd];
-
2784  mateIm = stateIm[mateInd];
-
2785 
-
2786  // swap amp with mate
-
2787  stateRe[mateInd] = stateRe[ampInd];
-
2788  stateIm[mateInd] = stateIm[ampInd];
-
2789  stateRe[ampInd] = mateRe;
-
2790  stateIm[ampInd] = mateIm;
-
2791  }
-
2792  }
-
2793 }
-
2794 
- -
2796  Qureg qureg, int ctrlMask, int targMask,
-
2797  ComplexArray stateVecIn,
-
2798  ComplexArray stateVecOut
-
2799 ) {
-
2800  long long int numAmps = qureg.numAmpsPerChunk;
-
2801  long long int globalOffset = qureg.chunkId * numAmps;
-
2802 
-
2803  /* stateVecOut is qureg's local state-vector partition, which we modify.
-
2804  * stateVecIn is the pair node's state-vector partition, in an order which
-
2805  * does not necessarily correlate to stateVecOut's
-
2806  */
-
2807  qreal* inReal = stateVecIn.real;
-
2808  qreal* inImag = stateVecIn.imag;
-
2809  qreal* outReal = stateVecOut.real;
-
2810  qreal* outImag = stateVecOut.imag;
-
2811 
-
2812  long long int outInd, outIndGlobal, inInd, inIndGlobal;
-
2813 
-
2814 # ifdef _OPENMP
-
2815 # pragma omp parallel \
-
2816  default (none) \
-
2817  shared (inReal,inImag,outReal,outImag, numAmps,globalOffset, ctrlMask,targMask) \
-
2818  private (outInd,outIndGlobal, inInd,inIndGlobal)
-
2819 # endif
-
2820  {
-
2821 # ifdef _OPENMP
-
2822 # pragma omp for schedule (static)
-
2823 # endif
-
2824  for (outInd = 0; outInd < numAmps; outInd++) {
-
2825 
-
2826  // modify amplitude only if control qubits are 1 for this state
-
2827  outIndGlobal = outInd + globalOffset;
-
2828  if (ctrlMask && ((ctrlMask & outIndGlobal) != ctrlMask))
-
2829  continue;
-
2830  /* it is a premature optimisation to remove this seemingly wasteful abort above,
-
2831  * because the maximum skipped amplitudes is 1/2 that stored in the node
-
2832  * (since this function is not called if all amps should be skipped)
-
2833  */
-
2834 
-
2835  /* unlike statevec_controlledNotDistributed(), we cannot assume stateVecOut
-
2836  * maps contiguously/parallel into stateVecIn; we must map each amplitude, bit-wise.
-
2837  * However, the arithmetic doesn't necessitate knowing the rank of stateVecIn
-
2838  */
-
2839  inIndGlobal = outIndGlobal ^ targMask;
-
2840  inInd = inIndGlobal % numAmps; // = inIndGlobal - pairRank * numAmps
-
2841 
-
2842  outReal[outInd] = inReal[inInd];
-
2843  outImag[outInd] = inImag[inInd];
-
2844  }
-
2845  }
-
2846 }
-
2847 
-
2848 void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
-
2849 {
-
2850  long long int sizeBlock, sizeHalfBlock;
-
2851  long long int thisBlock, // current block
-
2852  indexUp,indexLo; // current index and corresponding index in lower half block
-
2853 
-
2854  qreal stateRealUp,stateImagUp;
-
2855  long long int thisTask;
-
2856  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2857 
-
2858  // set dimensions
-
2859  sizeHalfBlock = 1LL << targetQubit;
-
2860  sizeBlock = 2LL * sizeHalfBlock;
-
2861 
-
2862  // Can't use qureg.stateVec as a private OMP var
-
2863  qreal *stateVecReal = qureg.stateVec.real;
-
2864  qreal *stateVecImag = qureg.stateVec.imag;
-
2865 
-
2866 # ifdef _OPENMP
-
2867 # pragma omp parallel \
-
2868  default (none) \
-
2869  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
-
2870  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2871 # endif
-
2872  {
-
2873 # ifdef _OPENMP
-
2874 # pragma omp for schedule (static)
-
2875 # endif
-
2876  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2877  thisBlock = thisTask / sizeHalfBlock;
-
2878  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2879  indexLo = indexUp + sizeHalfBlock;
-
2880 
-
2881  stateRealUp = stateVecReal[indexUp];
-
2882  stateImagUp = stateVecImag[indexUp];
-
2883 
-
2884  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2885  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2886  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2887  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2888  }
-
2889  }
-
2890 }
-
2891 
- -
2907  ComplexArray stateVecIn,
-
2908  ComplexArray stateVecOut,
-
2909  int updateUpper, int conjFac)
-
2910 {
-
2911 
-
2912  long long int thisTask;
-
2913  long long int numTasks=qureg.numAmpsPerChunk;
-
2914 
-
2915  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2916  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2917 
-
2918  int realSign=1, imagSign=1;
-
2919  if (updateUpper) imagSign=-1;
-
2920  else realSign = -1;
-
2921 
-
2922 # ifdef _OPENMP
-
2923 # pragma omp parallel \
-
2924  default (none) \
-
2925  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2926  realSign,imagSign, numTasks,conjFac) \
-
2927  private (thisTask)
-
2928 # endif
-
2929  {
-
2930 # ifdef _OPENMP
-
2931 # pragma omp for schedule (static)
-
2932 # endif
-
2933  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2934  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
-
2935  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
-
2936  }
-
2937  }
-
2938 }
-
2939 
-
2940 
-
2941 
-
2942 
-
2943 void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
-
2944 {
-
2945  long long int sizeBlock, sizeHalfBlock;
-
2946  long long int thisBlock, // current block
-
2947  indexUp,indexLo; // current index and corresponding index in lower half block
-
2948 
-
2949  qreal stateRealUp,stateImagUp;
-
2950  long long int thisTask;
-
2951  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2952  long long int chunkSize=qureg.numAmpsPerChunk;
-
2953  long long int chunkId=qureg.chunkId;
-
2954 
-
2955  int controlBit;
+
2758 # pragma omp parallel \
+
2759  default (none) \
+
2760  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
2761  numTasks,chunkId,chunkSize,controlQubit) \
+
2762  private (thisTask,controlBit)
+
2763 # endif
+
2764  {
+
2765 # ifdef _OPENMP
+
2766 # pragma omp for schedule (static)
+
2767 # endif
+
2768  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2769  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2770  if (controlBit){
+
2771  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
+
2772  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
+
2773  }
+
2774  }
+
2775  }
+
2776 }
+
2777 
+
2778 void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask) {
+
2779  long long int numAmps = qureg.numAmpsPerChunk;
+
2780  qreal* stateRe = qureg.stateVec.real;
+
2781  qreal* stateIm = qureg.stateVec.imag;
+
2782 
+
2783  long long int globalOffset = qureg.chunkId * numAmps;
+
2784 
+
2785  // each amplitude is swapped with a 'mate' amplitude
+
2786  long long int ampInd, mateInd, globalInd;
+
2787  qreal mateRe, mateIm;
+
2788 
+
2789 # ifdef _OPENMP
+
2790 # pragma omp parallel \
+
2791  default (none) \
+
2792  shared (stateRe,stateIm, numAmps, ctrlMask,targMask, globalOffset) \
+
2793  private (ampInd, mateInd,mateRe,mateIm, globalInd)
+
2794 # endif
+
2795  {
+
2796 # ifdef _OPENMP
+
2797 # pragma omp for schedule (static)
+
2798 # endif
+
2799  for (ampInd = 0; ampInd < numAmps; ampInd++) {
+
2800 
+
2801  /* it may be a premature optimisation to remove the seemingly wasteful continues below,
+
2802  * because the maximum skipped amplitudes is 1/2 that stored in the node
+
2803  * (e.g. since this function is not called if all amps should be skipped via controls),
+
2804  * and since we're memory-bandwidth bottlenecked.
+
2805  */
+
2806 
+
2807  // although amps are local, we may still be running in distributed mode,
+
2808  // and hence need to consult the global index to determine the values of
+
2809  // the control qubits
+
2810  globalInd = ampInd + globalOffset;
+
2811 
+
2812  // modify amplitude only if control qubits are 1 for this state
+
2813  if (ctrlMask && ((ctrlMask & globalInd) != ctrlMask))
+
2814  continue;
+
2815 
+
2816  mateInd = ampInd ^ targMask;
+
2817 
+
2818  // if the mate is behind, it was already processed
+
2819  if (mateInd < ampInd)
+
2820  continue;
+
2821 
+
2822  mateRe = stateRe[mateInd];
+
2823  mateIm = stateIm[mateInd];
+
2824 
+
2825  // swap amp with mate
+
2826  stateRe[mateInd] = stateRe[ampInd];
+
2827  stateIm[mateInd] = stateIm[ampInd];
+
2828  stateRe[ampInd] = mateRe;
+
2829  stateIm[ampInd] = mateIm;
+
2830  }
+
2831  }
+
2832 }
+
2833 
+ +
2835  Qureg qureg, int ctrlMask, int targMask,
+
2836  ComplexArray stateVecIn,
+
2837  ComplexArray stateVecOut
+
2838 ) {
+
2839  long long int numAmps = qureg.numAmpsPerChunk;
+
2840  long long int globalOffset = qureg.chunkId * numAmps;
+
2841 
+
2842  /* stateVecOut is qureg's local state-vector partition, which we modify.
+
2843  * stateVecIn is the pair node's state-vector partition, in an order which
+
2844  * does not necessarily correlate to stateVecOut's
+
2845  */
+
2846  qreal* inReal = stateVecIn.real;
+
2847  qreal* inImag = stateVecIn.imag;
+
2848  qreal* outReal = stateVecOut.real;
+
2849  qreal* outImag = stateVecOut.imag;
+
2850 
+
2851  long long int outInd, outIndGlobal, inInd, inIndGlobal;
+
2852 
+
2853 # ifdef _OPENMP
+
2854 # pragma omp parallel \
+
2855  default (none) \
+
2856  shared (inReal,inImag,outReal,outImag, numAmps,globalOffset, ctrlMask,targMask) \
+
2857  private (outInd,outIndGlobal, inInd,inIndGlobal)
+
2858 # endif
+
2859  {
+
2860 # ifdef _OPENMP
+
2861 # pragma omp for schedule (static)
+
2862 # endif
+
2863  for (outInd = 0; outInd < numAmps; outInd++) {
+
2864 
+
2865  // modify amplitude only if control qubits are 1 for this state
+
2866  outIndGlobal = outInd + globalOffset;
+
2867  if (ctrlMask && ((ctrlMask & outIndGlobal) != ctrlMask))
+
2868  continue;
+
2869  /* it is a premature optimisation to remove this seemingly wasteful abort above,
+
2870  * because the maximum skipped amplitudes is 1/2 that stored in the node
+
2871  * (since this function is not called if all amps should be skipped)
+
2872  */
+
2873 
+
2874  /* unlike statevec_controlledNotDistributed(), we cannot assume stateVecOut
+
2875  * maps contiguously/parallel into stateVecIn; we must map each amplitude, bit-wise.
+
2876  * However, the arithmetic doesn't necessitate knowing the rank of stateVecIn
+
2877  */
+
2878  inIndGlobal = outIndGlobal ^ targMask;
+
2879  inInd = inIndGlobal % numAmps; // = inIndGlobal - pairRank * numAmps
+
2880 
+
2881  outReal[outInd] = inReal[inInd];
+
2882  outImag[outInd] = inImag[inInd];
+
2883  }
+
2884  }
+
2885 }
+
2886 
+
2887 void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
+
2888 {
+
2889  long long int sizeBlock, sizeHalfBlock;
+
2890  long long int thisBlock, // current block
+
2891  indexUp,indexLo; // current index and corresponding index in lower half block
+
2892 
+
2893  qreal stateRealUp,stateImagUp;
+
2894  long long int thisTask;
+
2895  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2896 
+
2897  // set dimensions
+
2898  sizeHalfBlock = 1LL << targetQubit;
+
2899  sizeBlock = 2LL * sizeHalfBlock;
+
2900 
+
2901  // Can't use qureg.stateVec as a private OMP var
+
2902  qreal *stateVecReal = qureg.stateVec.real;
+
2903  qreal *stateVecImag = qureg.stateVec.imag;
+
2904 
+
2905 # ifdef _OPENMP
+
2906 # pragma omp parallel \
+
2907  default (none) \
+
2908  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
+
2909  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
+
2910 # endif
+
2911  {
+
2912 # ifdef _OPENMP
+
2913 # pragma omp for schedule (static)
+
2914 # endif
+
2915  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2916  thisBlock = thisTask / sizeHalfBlock;
+
2917  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2918  indexLo = indexUp + sizeHalfBlock;
+
2919 
+
2920  stateRealUp = stateVecReal[indexUp];
+
2921  stateImagUp = stateVecImag[indexUp];
+
2922 
+
2923  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
2924  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
2925  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
2926  stateVecImag[indexLo] = conjFac * stateRealUp;
+
2927  }
+
2928  }
+
2929 }
+
2930 
+ +
2946  ComplexArray stateVecIn,
+
2947  ComplexArray stateVecOut,
+
2948  int updateUpper, int conjFac)
+
2949 {
+
2950 
+
2951  long long int thisTask;
+
2952  long long int numTasks=qureg.numAmpsPerChunk;
+
2953 
+
2954  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2955  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
2956 
-
2957  // set dimensions
-
2958  sizeHalfBlock = 1LL << targetQubit;
-
2959  sizeBlock = 2LL * sizeHalfBlock;
+
2957  int realSign=1, imagSign=1;
+
2958  if (updateUpper) imagSign=-1;
+
2959  else realSign = -1;
2960 
-
2961  // Can't use qureg.stateVec as a private OMP var
-
2962  qreal *stateVecReal = qureg.stateVec.real;
-
2963  qreal *stateVecImag = qureg.stateVec.imag;
-
2964 
-
2965 # ifdef _OPENMP
-
2966 # pragma omp parallel \
-
2967  default (none) \
-
2968  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
-
2969  chunkSize,controlQubit,conjFac) \
-
2970  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
2961 # ifdef _OPENMP
+
2962 # pragma omp parallel \
+
2963  default (none) \
+
2964  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
2965  realSign,imagSign, numTasks,conjFac) \
+
2966  private (thisTask)
+
2967 # endif
+
2968  {
+
2969 # ifdef _OPENMP
+
2970 # pragma omp for schedule (static)
2971 # endif
-
2972  {
-
2973 # ifdef _OPENMP
-
2974 # pragma omp for schedule (static)
-
2975 # endif
-
2976  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2977  thisBlock = thisTask / sizeHalfBlock;
-
2978  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2979  indexLo = indexUp + sizeHalfBlock;
+
2972  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2973  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
+
2974  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
+
2975  }
+
2976  }
+
2977 }
+
2978 
+
2979 
2980 
-
2981  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2982  if (controlBit){
-
2983  stateRealUp = stateVecReal[indexUp];
-
2984  stateImagUp = stateVecImag[indexUp];
-
2985 
-
2986  // update under +-{{0, -i}, {i, 0}}
-
2987  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2988  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2989  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2990  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2991  }
-
2992  }
-
2993  }
-
2994 }
+
2981 
+
2982 void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
+
2983 {
+
2984  long long int sizeBlock, sizeHalfBlock;
+
2985  long long int thisBlock, // current block
+
2986  indexUp,indexLo; // current index and corresponding index in lower half block
+
2987 
+
2988  qreal stateRealUp,stateImagUp;
+
2989  long long int thisTask;
+
2990  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2991  long long int chunkSize=qureg.numAmpsPerChunk;
+
2992  long long int chunkId=qureg.chunkId;
+
2993 
+
2994  int controlBit;
2995 
-
2996 
-
2997 void statevec_controlledPauliYDistributed (Qureg qureg, int controlQubit,
-
2998  ComplexArray stateVecIn,
-
2999  ComplexArray stateVecOut, int conjFac)
-
3000 {
-
3001 
-
3002  long long int thisTask;
-
3003  long long int numTasks=qureg.numAmpsPerChunk;
-
3004  long long int chunkSize=qureg.numAmpsPerChunk;
-
3005  long long int chunkId=qureg.chunkId;
-
3006 
-
3007  int controlBit;
-
3008 
-
3009  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
3010  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
3011 
+
2996  // set dimensions
+
2997  sizeHalfBlock = 1LL << targetQubit;
+
2998  sizeBlock = 2LL * sizeHalfBlock;
+
2999 
+
3000  // Can't use qureg.stateVec as a private OMP var
+
3001  qreal *stateVecReal = qureg.stateVec.real;
+
3002  qreal *stateVecImag = qureg.stateVec.imag;
+
3003 
+
3004 # ifdef _OPENMP
+
3005 # pragma omp parallel \
+
3006  default (none) \
+
3007  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
+
3008  chunkSize,controlQubit,conjFac) \
+
3009  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
3010 # endif
+
3011  {
3012 # ifdef _OPENMP
-
3013 # pragma omp parallel \
-
3014  default (none) \
-
3015  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
3016  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
-
3017  private (thisTask,controlBit)
-
3018 # endif
-
3019  {
-
3020 # ifdef _OPENMP
-
3021 # pragma omp for schedule (static)
-
3022 # endif
-
3023  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3024  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
3025  if (controlBit){
-
3026  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
-
3027  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
-
3028  }
-
3029  }
-
3030  }
-
3031 }
-
3032 
-
3033 
+
3013 # pragma omp for schedule (static)
+
3014 # endif
+
3015  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3016  thisBlock = thisTask / sizeHalfBlock;
+
3017  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3018  indexLo = indexUp + sizeHalfBlock;
+
3019 
+
3020  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
+
3021  if (controlBit){
+
3022  stateRealUp = stateVecReal[indexUp];
+
3023  stateImagUp = stateVecImag[indexUp];
+
3024 
+
3025  // update under +-{{0, -i}, {i, 0}}
+
3026  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
3027  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
3028  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
3029  stateVecImag[indexLo] = conjFac * stateRealUp;
+
3030  }
+
3031  }
+
3032  }
+
3033 }
3034 
3035 
-
3036 
-
3037 
-
3038 
-
3039 void statevec_hadamardLocal(Qureg qureg, int targetQubit)
-
3040 {
-
3041  long long int sizeBlock, sizeHalfBlock;
-
3042  long long int thisBlock, // current block
-
3043  indexUp,indexLo; // current index and corresponding index in lower half block
-
3044 
-
3045  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
3046  long long int thisTask;
-
3047  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3048 
-
3049  // set dimensions
-
3050  sizeHalfBlock = 1LL << targetQubit;
-
3051  sizeBlock = 2LL * sizeHalfBlock;
-
3052 
-
3053  // Can't use qureg.stateVec as a private OMP var
-
3054  qreal *stateVecReal = qureg.stateVec.real;
-
3055  qreal *stateVecImag = qureg.stateVec.imag;
-
3056 
-
3057  qreal recRoot2 = 1.0/sqrt(2);
-
3058 
+
3036 void statevec_controlledPauliYDistributed (Qureg qureg, int controlQubit,
+
3037  ComplexArray stateVecIn,
+
3038  ComplexArray stateVecOut, int conjFac)
+
3039 {
+
3040 
+
3041  long long int thisTask;
+
3042  long long int numTasks=qureg.numAmpsPerChunk;
+
3043  long long int chunkSize=qureg.numAmpsPerChunk;
+
3044  long long int chunkId=qureg.chunkId;
+
3045 
+
3046  int controlBit;
+
3047 
+
3048  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
3049  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
3050 
+
3051 # ifdef _OPENMP
+
3052 # pragma omp parallel \
+
3053  default (none) \
+
3054  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
3055  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
+
3056  private (thisTask,controlBit)
+
3057 # endif
+
3058  {
3059 # ifdef _OPENMP
-
3060 # pragma omp parallel \
-
3061  default (none) \
-
3062  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
-
3063  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
3064 # endif
-
3065  {
-
3066 # ifdef _OPENMP
-
3067 # pragma omp for schedule (static)
-
3068 # endif
-
3069  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3070  thisBlock = thisTask / sizeHalfBlock;
-
3071  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3072  indexLo = indexUp + sizeHalfBlock;
+
3060 # pragma omp for schedule (static)
+
3061 # endif
+
3062  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3063  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
3064  if (controlBit){
+
3065  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
+
3066  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
+
3067  }
+
3068  }
+
3069  }
+
3070 }
+
3071 
+
3072 
3073 
-
3074  stateRealUp = stateVecReal[indexUp];
-
3075  stateImagUp = stateVecImag[indexUp];
+
3074 
+
3075 
3076 
-
3077  stateRealLo = stateVecReal[indexLo];
-
3078  stateImagLo = stateVecImag[indexLo];
-
3079 
-
3080  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
3081  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
3082 
-
3083  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
3084  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
3085  }
-
3086  }
-
3087 }
-
3088 
- -
3101  ComplexArray stateVecUp,
-
3102  ComplexArray stateVecLo,
-
3103  ComplexArray stateVecOut,
-
3104  int updateUpper)
-
3105 {
-
3106 
-
3107  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
3108  long long int thisTask;
-
3109  long long int numTasks=qureg.numAmpsPerChunk;
-
3110 
-
3111  int sign;
-
3112  if (updateUpper) sign=1;
-
3113  else sign=-1;
-
3114 
-
3115  qreal recRoot2 = 1.0/sqrt(2);
-
3116 
-
3117  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
3118  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
3119  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
3120 
-
3121 # ifdef _OPENMP
-
3122 # pragma omp parallel \
-
3123  default (none) \
-
3124  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
3125  recRoot2, sign, numTasks) \
-
3126  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
3127 # endif
-
3128  {
-
3129 # ifdef _OPENMP
-
3130 # pragma omp for schedule (static)
-
3131 # endif
-
3132  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3133  // store current state vector values in temp variables
-
3134  stateRealUp = stateVecRealUp[thisTask];
-
3135  stateImagUp = stateVecImagUp[thisTask];
-
3136 
-
3137  stateRealLo = stateVecRealLo[thisTask];
-
3138  stateImagLo = stateVecImagLo[thisTask];
-
3139 
-
3140  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
-
3141  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
-
3142  }
-
3143  }
-
3144 }
+
3077 
+
3078 void statevec_hadamardLocal(Qureg qureg, int targetQubit)
+
3079 {
+
3080  long long int sizeBlock, sizeHalfBlock;
+
3081  long long int thisBlock, // current block
+
3082  indexUp,indexLo; // current index and corresponding index in lower half block
+
3083 
+
3084  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
3085  long long int thisTask;
+
3086  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3087 
+
3088  // set dimensions
+
3089  sizeHalfBlock = 1LL << targetQubit;
+
3090  sizeBlock = 2LL * sizeHalfBlock;
+
3091 
+
3092  // Can't use qureg.stateVec as a private OMP var
+
3093  qreal *stateVecReal = qureg.stateVec.real;
+
3094  qreal *stateVecImag = qureg.stateVec.imag;
+
3095 
+
3096  qreal recRoot2 = 1.0/sqrt(2);
+
3097 
+
3098 # ifdef _OPENMP
+
3099 # pragma omp parallel \
+
3100  default (none) \
+
3101  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
+
3102  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
3103 # endif
+
3104  {
+
3105 # ifdef _OPENMP
+
3106 # pragma omp for schedule (static)
+
3107 # endif
+
3108  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3109  thisBlock = thisTask / sizeHalfBlock;
+
3110  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3111  indexLo = indexUp + sizeHalfBlock;
+
3112 
+
3113  stateRealUp = stateVecReal[indexUp];
+
3114  stateImagUp = stateVecImag[indexUp];
+
3115 
+
3116  stateRealLo = stateVecReal[indexLo];
+
3117  stateImagLo = stateVecImag[indexLo];
+
3118 
+
3119  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
+
3120  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
+
3121 
+
3122  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
+
3123  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
+
3124  }
+
3125  }
+
3126 }
+
3127 
+ +
3140  ComplexArray stateVecUp,
+
3141  ComplexArray stateVecLo,
+
3142  ComplexArray stateVecOut,
+
3143  int updateUpper)
+
3144 {
3145 
-
3146 void statevec_phaseShiftByTerm (Qureg qureg, int targetQubit, Complex term)
-
3147 {
-
3148  long long int index;
-
3149  long long int stateVecSize;
-
3150  int targetBit;
-
3151 
-
3152  long long int chunkSize=qureg.numAmpsPerChunk;
-
3153  long long int chunkId=qureg.chunkId;
-
3154 
-
3155  // dimension of the state vector
-
3156  stateVecSize = qureg.numAmpsPerChunk;
-
3157  qreal *stateVecReal = qureg.stateVec.real;
-
3158  qreal *stateVecImag = qureg.stateVec.imag;
-
3159 
-
3160  qreal stateRealLo, stateImagLo;
-
3161  qreal cosAngle = term.real;
-
3162  qreal sinAngle = term.imag;
-
3163 
-
3164 # ifdef _OPENMP
-
3165 # pragma omp parallel for \
-
3166  default (none) \
-
3167  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
-
3168  chunkId,chunkSize,targetQubit) \
-
3169  private (index,targetBit,stateRealLo,stateImagLo) \
-
3170  schedule (static)
-
3171 # endif
-
3172  for (index=0; index<stateVecSize; index++) {
-
3173 
-
3174  // update the coeff of the |1> state of the target qubit
-
3175  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
-
3176  if (targetBit) {
-
3177 
-
3178  stateRealLo = stateVecReal[index];
-
3179  stateImagLo = stateVecImag[index];
-
3180 
-
3181  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3182  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3183  }
-
3184  }
-
3185 }
-
3186 
-
3187 void statevec_controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
-
3188 {
-
3189  long long int index;
-
3190  long long int stateVecSize;
-
3191  int bit1, bit2;
-
3192 
-
3193  long long int chunkSize=qureg.numAmpsPerChunk;
-
3194  long long int chunkId=qureg.chunkId;
-
3195 
-
3196  // dimension of the state vector
-
3197  stateVecSize = qureg.numAmpsPerChunk;
-
3198  qreal *stateVecReal = qureg.stateVec.real;
-
3199  qreal *stateVecImag = qureg.stateVec.imag;
-
3200 
-
3201  qreal stateRealLo, stateImagLo;
-
3202  qreal cosAngle = cos(angle);
-
3203  qreal sinAngle = sin(angle);
-
3204 
-
3205 # ifdef _OPENMP
-
3206 # pragma omp parallel for \
-
3207  default (none) \
-
3208  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
-
3209  idQubit1,idQubit2,cosAngle,sinAngle ) \
-
3210  private (index,bit1,bit2,stateRealLo,stateImagLo) \
-
3211  schedule (static)
-
3212 # endif
-
3213  for (index=0; index<stateVecSize; index++) {
-
3214  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3215  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3216  if (bit1 && bit2) {
-
3217 
-
3218  stateRealLo = stateVecReal[index];
-
3219  stateImagLo = stateVecImag[index];
-
3220 
-
3221  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3222  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3223  }
-
3224  }
-
3225 }
-
3226 
-
3227 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
-
3228 {
-
3229  long long int index;
-
3230  long long int stateVecSize;
-
3231 
+
3146  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
3147  long long int thisTask;
+
3148  long long int numTasks=qureg.numAmpsPerChunk;
+
3149 
+
3150  int sign;
+
3151  if (updateUpper) sign=1;
+
3152  else sign=-1;
+
3153 
+
3154  qreal recRoot2 = 1.0/sqrt(2);
+
3155 
+
3156  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
3157  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
3158  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
3159 
+
3160 # ifdef _OPENMP
+
3161 # pragma omp parallel \
+
3162  default (none) \
+
3163  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
3164  recRoot2, sign, numTasks) \
+
3165  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
3166 # endif
+
3167  {
+
3168 # ifdef _OPENMP
+
3169 # pragma omp for schedule (static)
+
3170 # endif
+
3171  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3172  // store current state vector values in temp variables
+
3173  stateRealUp = stateVecRealUp[thisTask];
+
3174  stateImagUp = stateVecImagUp[thisTask];
+
3175 
+
3176  stateRealLo = stateVecRealLo[thisTask];
+
3177  stateImagLo = stateVecImagLo[thisTask];
+
3178 
+
3179  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
+
3180  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
+
3181  }
+
3182  }
+
3183 }
+
3184 
+
3185 void statevec_phaseShiftByTerm (Qureg qureg, int targetQubit, Complex term)
+
3186 {
+
3187  long long int index;
+
3188  long long int stateVecSize;
+
3189  int targetBit;
+
3190 
+
3191  long long int chunkSize=qureg.numAmpsPerChunk;
+
3192  long long int chunkId=qureg.chunkId;
+
3193 
+
3194  // dimension of the state vector
+
3195  stateVecSize = qureg.numAmpsPerChunk;
+
3196  qreal *stateVecReal = qureg.stateVec.real;
+
3197  qreal *stateVecImag = qureg.stateVec.imag;
+
3198 
+
3199  qreal stateRealLo, stateImagLo;
+
3200  qreal cosAngle = term.real;
+
3201  qreal sinAngle = term.imag;
+
3202 
+
3203 # ifdef _OPENMP
+
3204 # pragma omp parallel for \
+
3205  default (none) \
+
3206  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
+
3207  chunkId,chunkSize,targetQubit) \
+
3208  private (index,targetBit,stateRealLo,stateImagLo) \
+
3209  schedule (static)
+
3210 # endif
+
3211  for (index=0; index<stateVecSize; index++) {
+
3212 
+
3213  // update the coeff of the |1> state of the target qubit
+
3214  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
+
3215  if (targetBit) {
+
3216 
+
3217  stateRealLo = stateVecReal[index];
+
3218  stateImagLo = stateVecImag[index];
+
3219 
+
3220  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3221  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3222  }
+
3223  }
+
3224 }
+
3225 
+
3226 void statevec_controlledPhaseShift (Qureg qureg, int idQubit1, int idQubit2, qreal angle)
+
3227 {
+
3228  long long int index;
+
3229  long long int stateVecSize;
+
3230  int bit1, bit2;
+
3231 
3232  long long int chunkSize=qureg.numAmpsPerChunk;
3233  long long int chunkId=qureg.chunkId;
3234 
-
3235  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3236 
-
3237  stateVecSize = qureg.numAmpsPerChunk;
-
3238  qreal *stateVecReal = qureg.stateVec.real;
-
3239  qreal *stateVecImag = qureg.stateVec.imag;
-
3240 
-
3241  qreal stateRealLo, stateImagLo;
-
3242  qreal cosAngle = cos(angle);
-
3243  qreal sinAngle = sin(angle);
-
3244 
-
3245 # ifdef _OPENMP
-
3246 # pragma omp parallel \
-
3247  default (none) \
-
3248  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3249  private (index, stateRealLo, stateImagLo)
-
3250 # endif
-
3251  {
-
3252 # ifdef _OPENMP
-
3253 # pragma omp for schedule (static)
-
3254 # endif
-
3255  for (index=0; index<stateVecSize; index++) {
-
3256  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3257 
-
3258  stateRealLo = stateVecReal[index];
-
3259  stateImagLo = stateVecImag[index];
-
3260 
-
3261  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3262  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3263  }
-
3264  }
-
3265  }
-
3266 }
-
3267 
-
3268 int getBitMaskParity(long long int mask) {
-
3269  int parity = 0;
-
3270  while (mask) {
-
3271  parity = !parity;
-
3272  mask = mask & (mask-1);
-
3273  }
-
3274  return parity;
-
3275 }
-
3276 
-
3277 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
-
3278 {
-
3279  long long int index;
-
3280  long long int stateVecSize;
-
3281 
-
3282  long long int chunkSize=qureg.numAmpsPerChunk;
-
3283  long long int chunkId=qureg.chunkId;
-
3284 
-
3285  stateVecSize = qureg.numAmpsPerChunk;
-
3286  qreal *stateVecReal = qureg.stateVec.real;
-
3287  qreal *stateVecImag = qureg.stateVec.imag;
-
3288 
-
3289  qreal stateReal, stateImag;
-
3290  qreal cosAngle = cos(angle/2.0);
-
3291  qreal sinAngle = sin(angle/2.0);
-
3292 
-
3293  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3294  // exp(-angle/2 i fac_j)|j>
-
3295  int fac;
-
3296 
-
3297 # ifdef _OPENMP
-
3298 # pragma omp parallel \
-
3299  default (none) \
-
3300  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3301  private (index, fac, stateReal, stateImag)
-
3302 # endif
-
3303  {
-
3304 # ifdef _OPENMP
-
3305 # pragma omp for schedule (static)
-
3306 # endif
-
3307  for (index=0; index<stateVecSize; index++) {
-
3308  stateReal = stateVecReal[index];
-
3309  stateImag = stateVecImag[index];
-
3310 
-
3311  // odd-parity target qubits get fac_j = -1
-
3312  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
-
3313  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3314  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3315  }
-
3316  }
-
3317 }
-
3318 
-
3319 void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
-
3320 {
-
3321  long long int offset = qureg.chunkId * qureg.numAmpsPerChunk;
-
3322 
-
3323  long long int stateVecSize = qureg.numAmpsPerChunk;
-
3324  qreal *stateVecReal = qureg.stateVec.real;
-
3325  qreal *stateVecImag = qureg.stateVec.imag;
-
3326 
-
3327  qreal stateReal, stateImag;
-
3328  qreal cosAngle = cos(angle/2.0);
-
3329  qreal sinAngle = sin(angle/2.0);
-
3330 
-
3331  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3332  // exp(-angle/2 i fac_j)|j>
-
3333  int fac;
-
3334  long long int index, globalIndex;
+
3235  // dimension of the state vector
+
3236  stateVecSize = qureg.numAmpsPerChunk;
+
3237  qreal *stateVecReal = qureg.stateVec.real;
+
3238  qreal *stateVecImag = qureg.stateVec.imag;
+
3239 
+
3240  qreal stateRealLo, stateImagLo;
+
3241  qreal cosAngle = cos(angle);
+
3242  qreal sinAngle = sin(angle);
+
3243 
+
3244 # ifdef _OPENMP
+
3245 # pragma omp parallel for \
+
3246  default (none) \
+
3247  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
+
3248  idQubit1,idQubit2,cosAngle,sinAngle ) \
+
3249  private (index,bit1,bit2,stateRealLo,stateImagLo) \
+
3250  schedule (static)
+
3251 # endif
+
3252  for (index=0; index<stateVecSize; index++) {
+
3253  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
+
3254  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
+
3255  if (bit1 && bit2) {
+
3256 
+
3257  stateRealLo = stateVecReal[index];
+
3258  stateImagLo = stateVecImag[index];
+
3259 
+
3260  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3261  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3262  }
+
3263  }
+
3264 }
+
3265 
+
3266 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
+
3267 {
+
3268  long long int index;
+
3269  long long int stateVecSize;
+
3270 
+
3271  long long int chunkSize=qureg.numAmpsPerChunk;
+
3272  long long int chunkId=qureg.chunkId;
+
3273 
+
3274  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
3275 
+
3276  stateVecSize = qureg.numAmpsPerChunk;
+
3277  qreal *stateVecReal = qureg.stateVec.real;
+
3278  qreal *stateVecImag = qureg.stateVec.imag;
+
3279 
+
3280  qreal stateRealLo, stateImagLo;
+
3281  qreal cosAngle = cos(angle);
+
3282  qreal sinAngle = sin(angle);
+
3283 
+
3284 # ifdef _OPENMP
+
3285 # pragma omp parallel \
+
3286  default (none) \
+
3287  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
+
3288  private (index, stateRealLo, stateImagLo)
+
3289 # endif
+
3290  {
+
3291 # ifdef _OPENMP
+
3292 # pragma omp for schedule (static)
+
3293 # endif
+
3294  for (index=0; index<stateVecSize; index++) {
+
3295  if (mask == (mask & (index+chunkId*chunkSize)) ){
+
3296 
+
3297  stateRealLo = stateVecReal[index];
+
3298  stateImagLo = stateVecImag[index];
+
3299 
+
3300  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3301  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3302  }
+
3303  }
+
3304  }
+
3305 }
+
3306 
+
3307 int getBitMaskParity(long long int mask) {
+
3308  int parity = 0;
+
3309  while (mask) {
+
3310  parity = !parity;
+
3311  mask = mask & (mask-1);
+
3312  }
+
3313  return parity;
+
3314 }
+
3315 
+
3316 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
+
3317 {
+
3318  long long int index;
+
3319  long long int stateVecSize;
+
3320 
+
3321  long long int chunkSize=qureg.numAmpsPerChunk;
+
3322  long long int chunkId=qureg.chunkId;
+
3323 
+
3324  stateVecSize = qureg.numAmpsPerChunk;
+
3325  qreal *stateVecReal = qureg.stateVec.real;
+
3326  qreal *stateVecImag = qureg.stateVec.imag;
+
3327 
+
3328  qreal stateReal, stateImag;
+
3329  qreal cosAngle = cos(angle/2.0);
+
3330  qreal sinAngle = sin(angle/2.0);
+
3331 
+
3332  // = +-1, to flip sinAngle based on target qubit parity, to effect
+
3333  // exp(-angle/2 i fac_j)|j>
+
3334  int fac;
3335 
3336 # ifdef _OPENMP
3337 # pragma omp parallel \
3338  default (none) \
-
3339  shared (offset, stateVecSize, stateVecReal,stateVecImag, ctrlMask,targMask, cosAngle,sinAngle) \
-
3340  private (index,globalIndex, fac, stateReal,stateImag)
+
3339  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
+
3340  private (index, fac, stateReal, stateImag)
3341 # endif
3342  {
3343 # ifdef _OPENMP
@@ -3271,467 +3271,467 @@
3347  stateReal = stateVecReal[index];
3348  stateImag = stateVecImag[index];
3349 
-
3350  // states with not-all-one control qubits are unmodified
-
3351  globalIndex = index + offset;
-
3352  if (ctrlMask && ((ctrlMask & globalIndex) != ctrlMask))
-
3353  continue;
-
3354 
-
3355  // odd-parity target qubits get fac_j = -1 (avoid thread divergence)
-
3356  fac = 1-2*getBitMaskParity(targMask & globalIndex);
-
3357  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3358  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3359  }
-
3360  }
-
3361 }
-
3362 
- -
3364 
-
3365  // computes first local index containing a diagonal element
-
3366  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3367  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3368  long long int diagSpacing = 1LL + densityDim;
-
3369  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3370  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3371  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3372  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3373 
-
3374  // computes how many diagonals are contained in this chunk
-
3375  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3376  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3377  numDiagsInThisChunk -= 1;
-
3378 
-
3379  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3380  long long int basisStateInd; // current diagonal index being considered
-
3381  long long int index; // index in the local chunk
-
3382 
-
3383  qreal zeroProb = 0;
-
3384  qreal *stateVecReal = qureg.stateVec.real;
-
3385 
-
3386 # ifdef _OPENMP
-
3387 # pragma omp parallel \
-
3388  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
-
3389  private (visitedDiags, basisStateInd, index) \
-
3390  reduction ( +:zeroProb )
-
3391 # endif
-
3392  {
-
3393 # ifdef _OPENMP
-
3394 # pragma omp for schedule (static)
-
3395 # endif
-
3396  // sums the diagonal elems of the density matrix where measureQubit=0
-
3397  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3398 
-
3399  basisStateInd = numPrevDiags + visitedDiags;
-
3400  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3401 
-
3402  if (extractBit(measureQubit, basisStateInd) == 0)
-
3403  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
-
3404 
-
3405  }
-
3406  }
-
3407 
-
3408  return zeroProb;
-
3409 }
-
3410 
- -
3419  int measureQubit)
-
3420 {
-
3421  // ----- sizes
-
3422  long long int sizeBlock, // size of blocks
-
3423  sizeHalfBlock; // size of blocks halved
-
3424  // ----- indices
-
3425  long long int thisBlock, // current block
-
3426  index; // current index for first half block
-
3427  // ----- measured probability
-
3428  qreal totalProbability; // probability (returned) value
-
3429  // ----- temp variables
-
3430  long long int thisTask;
-
3431  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3432 
-
3433  // ---------------------------------------------------------------- //
-
3434  // dimensions //
-
3435  // ---------------------------------------------------------------- //
-
3436  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3437  // and then the number to skip
-
3438  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3439 
-
3440  // initialise returned value
-
3441  totalProbability = 0.0;
-
3442 
-
3443  qreal *stateVecReal = qureg.stateVec.real;
-
3444  qreal *stateVecImag = qureg.stateVec.imag;
-
3445 
-
3446 # ifdef _OPENMP
-
3447 # pragma omp parallel \
-
3448  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
-
3449  private (thisTask,thisBlock,index) \
-
3450  reduction ( +:totalProbability )
-
3451 # endif
-
3452  {
-
3453 # ifdef _OPENMP
-
3454 # pragma omp for schedule (static)
-
3455 # endif
-
3456  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3457  thisBlock = thisTask / sizeHalfBlock;
-
3458  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3459 
-
3460  totalProbability += stateVecReal[index]*stateVecReal[index]
-
3461  + stateVecImag[index]*stateVecImag[index];
-
3462  }
-
3463  }
-
3464  return totalProbability;
-
3465 }
-
3466 
- -
3475  // ----- measured probability
-
3476  qreal totalProbability; // probability (returned) value
-
3477  // ----- temp variables
-
3478  long long int thisTask; // task based approach for expose loop with small granularity
-
3479  long long int numTasks=qureg.numAmpsPerChunk;
-
3480 
-
3481  // ---------------------------------------------------------------- //
-
3482  // find probability //
-
3483  // ---------------------------------------------------------------- //
+
3350  // odd-parity target qubits get fac_j = -1
+
3351  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
+
3352  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
3353  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
3354  }
+
3355  }
+
3356 }
+
3357 
+
3358 void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
+
3359 {
+
3360  long long int offset = qureg.chunkId * qureg.numAmpsPerChunk;
+
3361 
+
3362  long long int stateVecSize = qureg.numAmpsPerChunk;
+
3363  qreal *stateVecReal = qureg.stateVec.real;
+
3364  qreal *stateVecImag = qureg.stateVec.imag;
+
3365 
+
3366  qreal stateReal, stateImag;
+
3367  qreal cosAngle = cos(angle/2.0);
+
3368  qreal sinAngle = sin(angle/2.0);
+
3369 
+
3370  // = +-1, to flip sinAngle based on target qubit parity, to effect
+
3371  // exp(-angle/2 i fac_j)|j>
+
3372  int fac;
+
3373  long long int index, globalIndex;
+
3374 
+
3375 # ifdef _OPENMP
+
3376 # pragma omp parallel \
+
3377  default (none) \
+
3378  shared (offset, stateVecSize, stateVecReal,stateVecImag, ctrlMask,targMask, cosAngle,sinAngle) \
+
3379  private (index,globalIndex, fac, stateReal,stateImag)
+
3380 # endif
+
3381  {
+
3382 # ifdef _OPENMP
+
3383 # pragma omp for schedule (static)
+
3384 # endif
+
3385  for (index=0; index<stateVecSize; index++) {
+
3386  stateReal = stateVecReal[index];
+
3387  stateImag = stateVecImag[index];
+
3388 
+
3389  // states with not-all-one control qubits are unmodified
+
3390  globalIndex = index + offset;
+
3391  if (ctrlMask && ((ctrlMask & globalIndex) != ctrlMask))
+
3392  continue;
+
3393 
+
3394  // odd-parity target qubits get fac_j = -1 (avoid thread divergence)
+
3395  fac = 1-2*getBitMaskParity(targMask & globalIndex);
+
3396  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
3397  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
3398  }
+
3399  }
+
3400 }
+
3401 
+ +
3403 
+
3404  // computes first local index containing a diagonal element
+
3405  long long int localNumAmps = qureg.numAmpsPerChunk;
+
3406  long long int densityDim = (1LL << qureg.numQubitsRepresented);
+
3407  long long int diagSpacing = 1LL + densityDim;
+
3408  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
+
3409  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
+
3410  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
3411  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
+
3412 
+
3413  // computes how many diagonals are contained in this chunk
+
3414  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
+
3415  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
+
3416  numDiagsInThisChunk -= 1;
+
3417 
+
3418  long long int visitedDiags; // number of visited diagonals in this chunk so far
+
3419  long long int basisStateInd; // current diagonal index being considered
+
3420  long long int index; // index in the local chunk
+
3421 
+
3422  qreal zeroProb = 0;
+
3423  qreal *stateVecReal = qureg.stateVec.real;
+
3424 
+
3425 # ifdef _OPENMP
+
3426 # pragma omp parallel \
+
3427  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
+
3428  private (visitedDiags, basisStateInd, index) \
+
3429  reduction ( +:zeroProb )
+
3430 # endif
+
3431  {
+
3432 # ifdef _OPENMP
+
3433 # pragma omp for schedule (static)
+
3434 # endif
+
3435  // sums the diagonal elems of the density matrix where measureQubit=0
+
3436  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
+
3437 
+
3438  basisStateInd = numPrevDiags + visitedDiags;
+
3439  index = localIndNextDiag + diagSpacing * visitedDiags;
+
3440 
+
3441  if (extractBit(measureQubit, basisStateInd) == 0)
+
3442  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
+
3443 
+
3444  }
+
3445  }
+
3446 
+
3447  return zeroProb;
+
3448 }
+
3449 
+ +
3458  int measureQubit)
+
3459 {
+
3460  // ----- sizes
+
3461  long long int sizeBlock, // size of blocks
+
3462  sizeHalfBlock; // size of blocks halved
+
3463  // ----- indices
+
3464  long long int thisBlock, // current block
+
3465  index; // current index for first half block
+
3466  // ----- measured probability
+
3467  qreal totalProbability; // probability (returned) value
+
3468  // ----- temp variables
+
3469  long long int thisTask;
+
3470  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3471 
+
3472  // ---------------------------------------------------------------- //
+
3473  // dimensions //
+
3474  // ---------------------------------------------------------------- //
+
3475  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
3476  // and then the number to skip
+
3477  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
3478 
+
3479  // initialise returned value
+
3480  totalProbability = 0.0;
+
3481 
+
3482  qreal *stateVecReal = qureg.stateVec.real;
+
3483  qreal *stateVecImag = qureg.stateVec.imag;
3484 
-
3485  // initialise returned value
-
3486  totalProbability = 0.0;
-
3487 
-
3488  qreal *stateVecReal = qureg.stateVec.real;
-
3489  qreal *stateVecImag = qureg.stateVec.imag;
-
3490 
-
3491 # ifdef _OPENMP
-
3492 # pragma omp parallel \
-
3493  shared (numTasks,stateVecReal,stateVecImag) \
-
3494  private (thisTask) \
-
3495  reduction ( +:totalProbability )
-
3496 # endif
-
3497  {
-
3498 # ifdef _OPENMP
-
3499 # pragma omp for schedule (static)
-
3500 # endif
-
3501  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3502  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
-
3503  + stateVecImag[thisTask]*stateVecImag[thisTask];
-
3504  }
-
3505  }
-
3506 
-
3507  return totalProbability;
-
3508 }
-
3509 
-
3510 void statevec_calcProbOfAllOutcomesLocal(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
-
3511 
-
3512  /* Below, we manually reduce amplitudes into outcomeProbs by using atomic update.
-
3513  * This maintains OpenMP 3.1 compatibility. An alternative is to use array reduction
-
3514  * (requires OpenMP 4.5, limits #qubits since outcomeProbs must be a local stack array)
-
3515  * or a dynamic list of omp locks (duplicates memory cost of outcomeProbs).
-
3516  * Using locks was always slower than the method below. Using reduction was only
-
3517  * faster for very few threads, or very few outcomeProbs.
-
3518  */
+
3485 # ifdef _OPENMP
+
3486 # pragma omp parallel \
+
3487  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
+
3488  private (thisTask,thisBlock,index) \
+
3489  reduction ( +:totalProbability )
+
3490 # endif
+
3491  {
+
3492 # ifdef _OPENMP
+
3493 # pragma omp for schedule (static)
+
3494 # endif
+
3495  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3496  thisBlock = thisTask / sizeHalfBlock;
+
3497  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3498 
+
3499  totalProbability += stateVecReal[index]*stateVecReal[index]
+
3500  + stateVecImag[index]*stateVecImag[index];
+
3501  }
+
3502  }
+
3503  return totalProbability;
+
3504 }
+
3505 
+ +
3514  // ----- measured probability
+
3515  qreal totalProbability; // probability (returned) value
+
3516  // ----- temp variables
+
3517  long long int thisTask; // task based approach for expose loop with small granularity
+
3518  long long int numTasks=qureg.numAmpsPerChunk;
3519 
-
3520  long long int numOutcomeProbs = (1 << numQubits);
-
3521  long long int j;
-
3522 
-
3523  // clear outcomeProbs (in parallel, in case it's large)
-
3524 # ifdef _OPENMP
-
3525 # pragma omp parallel \
-
3526  default (none) \
-
3527  shared (numOutcomeProbs,outcomeProbs) \
-
3528  private (j)
-
3529 # endif
-
3530  {
-
3531 # ifdef _OPENMP
-
3532 # pragma omp for schedule (static)
-
3533 # endif
-
3534  for (j=0; j<numOutcomeProbs; j++)
-
3535  outcomeProbs[j] = 0;
-
3536  }
-
3537 
-
3538  long long int numTasks = qureg.numAmpsPerChunk;
-
3539  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk;
-
3540  qreal* stateRe = qureg.stateVec.real;
-
3541  qreal* stateIm = qureg.stateVec.imag;
-
3542 
-
3543  long long int i;
-
3544  long long int outcomeInd;
-
3545  int q;
-
3546  qreal prob;
-
3547 
-
3548 # ifdef _OPENMP
-
3549 # pragma omp parallel \
-
3550  shared (numTasks,offset, qubits,numQubits, stateRe,stateIm, outcomeProbs) \
-
3551  private (i, q, outcomeInd, prob)
-
3552 # endif
-
3553  {
-
3554 # ifdef _OPENMP
-
3555 # pragma omp for schedule (static)
-
3556 # endif
-
3557  // every amplitude contributes to a single element of retProbs
-
3558  for (i=0; i<numTasks; i++) {
-
3559 
-
3560  // determine index informed by qubits outcome
-
3561  outcomeInd = 0;
-
3562  for (q=0; q<numQubits; q++)
-
3563  outcomeInd += extractBit(qubits[q], i + offset) * (1LL << q);
-
3564 
-
3565  prob = stateRe[i]*stateRe[i] + stateIm[i]*stateIm[i];
-
3566 
-
3567  // atomicly update corresponding outcome array element
-
3568  # ifdef _OPENMP
-
3569  # pragma omp atomic update
-
3570  # endif
-
3571  outcomeProbs[outcomeInd] += prob;
-
3572  }
-
3573  }
-
3574 }
-
3575 
-
3576 void densmatr_calcProbOfAllOutcomesLocal(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
+
3520  // ---------------------------------------------------------------- //
+
3521  // find probability //
+
3522  // ---------------------------------------------------------------- //
+
3523 
+
3524  // initialise returned value
+
3525  totalProbability = 0.0;
+
3526 
+
3527  qreal *stateVecReal = qureg.stateVec.real;
+
3528  qreal *stateVecImag = qureg.stateVec.imag;
+
3529 
+
3530 # ifdef _OPENMP
+
3531 # pragma omp parallel \
+
3532  shared (numTasks,stateVecReal,stateVecImag) \
+
3533  private (thisTask) \
+
3534  reduction ( +:totalProbability )
+
3535 # endif
+
3536  {
+
3537 # ifdef _OPENMP
+
3538 # pragma omp for schedule (static)
+
3539 # endif
+
3540  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3541  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
+
3542  + stateVecImag[thisTask]*stateVecImag[thisTask];
+
3543  }
+
3544  }
+
3545 
+
3546  return totalProbability;
+
3547 }
+
3548 
+
3549 void statevec_calcProbOfAllOutcomesLocal(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
+
3550 
+
3551  /* Below, we manually reduce amplitudes into outcomeProbs by using atomic update.
+
3552  * This maintains OpenMP 3.1 compatibility. An alternative is to use array reduction
+
3553  * (requires OpenMP 4.5, limits #qubits since outcomeProbs must be a local stack array)
+
3554  * or a dynamic list of omp locks (duplicates memory cost of outcomeProbs).
+
3555  * Using locks was always slower than the method below. Using reduction was only
+
3556  * faster for very few threads, or very few outcomeProbs.
+
3557  * Finally, we exclude the 'update' clause after 'atomic' to maintain MSVC compatibility
+
3558  */
+
3559 
+
3560  long long int numOutcomeProbs = (1 << numQubits);
+
3561  long long int j;
+
3562 
+
3563  // clear outcomeProbs (in parallel, in case it's large)
+
3564 # ifdef _OPENMP
+
3565 # pragma omp parallel \
+
3566  default (none) \
+
3567  shared (numOutcomeProbs,outcomeProbs) \
+
3568  private (j)
+
3569 # endif
+
3570  {
+
3571 # ifdef _OPENMP
+
3572 # pragma omp for schedule (static)
+
3573 # endif
+
3574  for (j=0; j<numOutcomeProbs; j++)
+
3575  outcomeProbs[j] = 0;
+
3576  }
3577 
-
3578  // clear outcomeProbs (in parallel, in case it's large)
-
3579  long long int numOutcomeProbs = (1 << numQubits);
-
3580  long long int j;
-
3581 
-
3582 # ifdef _OPENMP
-
3583 # pragma omp parallel \
-
3584  default (none) \
-
3585  shared (numOutcomeProbs,outcomeProbs) \
-
3586  private (j)
-
3587 # endif
-
3588  {
-
3589 # ifdef _OPENMP
-
3590 # pragma omp for schedule (static)
-
3591 # endif
-
3592  for (j=0; j<numOutcomeProbs; j++)
-
3593  outcomeProbs[j] = 0;
-
3594  }
-
3595 
-
3596  // compute first local index containing a diagonal element
-
3597  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3598  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3599  long long int diagSpacing = 1LL + densityDim;
-
3600  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3601  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3602  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3603  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3604 
-
3605  // computes how many diagonals are contained in this chunk
-
3606  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3607  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3608  numDiagsInThisChunk -= 1;
-
3609 
-
3610  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3611  long long int basisStateInd; // current diagonal index being considered
-
3612  long long int index; // index in the local chunk
-
3613 
-
3614  int q;
-
3615  long long int outcomeInd;
-
3616  qreal *stateRe = qureg.stateVec.real;
+
3578  long long int numTasks = qureg.numAmpsPerChunk;
+
3579  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk;
+
3580  qreal* stateRe = qureg.stateVec.real;
+
3581  qreal* stateIm = qureg.stateVec.imag;
+
3582 
+
3583  long long int i;
+
3584  long long int outcomeInd;
+
3585  int q;
+
3586  qreal prob;
+
3587 
+
3588 # ifdef _OPENMP
+
3589 # pragma omp parallel \
+
3590  shared (numTasks,offset, qubits,numQubits, stateRe,stateIm, outcomeProbs) \
+
3591  private (i, q, outcomeInd, prob)
+
3592 # endif
+
3593  {
+
3594 # ifdef _OPENMP
+
3595 # pragma omp for schedule (static)
+
3596 # endif
+
3597  // every amplitude contributes to a single element of retProbs
+
3598  for (i=0; i<numTasks; i++) {
+
3599 
+
3600  // determine index informed by qubits outcome
+
3601  outcomeInd = 0;
+
3602  for (q=0; q<numQubits; q++)
+
3603  outcomeInd += extractBit(qubits[q], i + offset) * (1LL << q);
+
3604 
+
3605  prob = stateRe[i]*stateRe[i] + stateIm[i]*stateIm[i];
+
3606 
+
3607  // atomicly update corresponding outcome array element
+
3608  # ifdef _OPENMP
+
3609  # pragma omp atomic
+
3610  # endif
+
3611  outcomeProbs[outcomeInd] += prob;
+
3612  }
+
3613  }
+
3614 }
+
3615 
+
3616 void densmatr_calcProbOfAllOutcomesLocal(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
3617 
-
3618 # ifdef _OPENMP
-
3619 # pragma omp parallel \
-
3620  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateRe, numDiagsInThisChunk, qubits,numQubits, outcomeProbs) \
-
3621  private (visitedDiags, basisStateInd, index, q,outcomeInd)
-
3622 # endif
-
3623  {
-
3624 # ifdef _OPENMP
-
3625 # pragma omp for schedule (static)
-
3626 # endif
-
3627  // sums the diagonal elems of the density matrix where measureQubit=0
-
3628  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3629 
-
3630  basisStateInd = numPrevDiags + visitedDiags;
-
3631  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3632 
-
3633  // determine outcome implied by basisStateInd
-
3634  outcomeInd = 0;
-
3635  for (q=0; q<numQubits; q++)
-
3636  outcomeInd += extractBit(qubits[q], basisStateInd) * (1LL << q);
-
3637 
-
3638  // atomicly update corresponding outcome array element
-
3639  # ifdef _OPENMP
-
3640  # pragma omp atomic update
-
3641  # endif
-
3642  outcomeProbs[outcomeInd] += stateRe[index];
-
3643  }
-
3644  }
-
3645 }
-
3646 
-
3647 void statevec_controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
-
3648 {
-
3649  long long int index;
-
3650  long long int stateVecSize;
-
3651  int bit1, bit2;
-
3652 
-
3653  long long int chunkSize=qureg.numAmpsPerChunk;
-
3654  long long int chunkId=qureg.chunkId;
-
3655 
-
3656  // dimension of the state vector
-
3657  stateVecSize = qureg.numAmpsPerChunk;
-
3658  qreal *stateVecReal = qureg.stateVec.real;
-
3659  qreal *stateVecImag = qureg.stateVec.imag;
-
3660 
-
3661 # ifdef _OPENMP
-
3662 # pragma omp parallel for \
-
3663  default (none) \
-
3664  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
-
3665  private (index,bit1,bit2) \
-
3666  schedule (static)
-
3667 # endif
-
3668  for (index=0; index<stateVecSize; index++) {
-
3669  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3670  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3671  if (bit1 && bit2) {
-
3672  stateVecReal [index] = - stateVecReal [index];
-
3673  stateVecImag [index] = - stateVecImag [index];
-
3674  }
-
3675  }
-
3676 }
-
3677 
-
3678 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
-
3679 {
-
3680  long long int index;
-
3681  long long int stateVecSize;
-
3682 
-
3683  long long int chunkSize=qureg.numAmpsPerChunk;
-
3684  long long int chunkId=qureg.chunkId;
-
3685 
-
3686  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3687 
-
3688  stateVecSize = qureg.numAmpsPerChunk;
-
3689  qreal *stateVecReal = qureg.stateVec.real;
-
3690  qreal *stateVecImag = qureg.stateVec.imag;
-
3691 
-
3692 # ifdef _OPENMP
-
3693 # pragma omp parallel \
-
3694  default (none) \
-
3695  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
-
3696  private (index)
-
3697 # endif
-
3698  {
-
3699 # ifdef _OPENMP
-
3700 # pragma omp for schedule (static)
-
3701 # endif
-
3702  for (index=0; index<stateVecSize; index++) {
-
3703  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3704  stateVecReal [index] = - stateVecReal [index];
-
3705  stateVecImag [index] = - stateVecImag [index];
-
3706  }
-
3707  }
-
3708  }
-
3709 }
-
3710 
-
3727 void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
-
3728 {
-
3729  // ----- sizes
-
3730  long long int sizeBlock, // size of blocks
-
3731  sizeHalfBlock; // size of blocks halved
-
3732  // ----- indices
-
3733  long long int thisBlock, // current block
-
3734  index; // current index for first half block
-
3735  // ----- measured probability
-
3736  qreal renorm; // probability (returned) value
-
3737  // ----- temp variables
-
3738  long long int thisTask; // task based approach for expose loop with small granularity
-
3739  // (good for shared memory parallelism)
-
3740  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3741 
-
3742  // ---------------------------------------------------------------- //
-
3743  // dimensions //
-
3744  // ---------------------------------------------------------------- //
-
3745  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3746  // and then the number to skip
-
3747  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3748 
-
3749  renorm=1/sqrt(totalProbability);
-
3750  qreal *stateVecReal = qureg.stateVec.real;
-
3751  qreal *stateVecImag = qureg.stateVec.imag;
-
3752 
-
3753 
-
3754 # ifdef _OPENMP
-
3755 # pragma omp parallel \
-
3756  default (none) \
-
3757  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
-
3758  private (thisTask,thisBlock,index)
-
3759 # endif
-
3760  {
-
3761  if (outcome==0){
-
3762  // measure qubit is 0
-
3763 # ifdef _OPENMP
-
3764 # pragma omp for schedule (static)
-
3765 # endif
-
3766  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3767  thisBlock = thisTask / sizeHalfBlock;
-
3768  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3769  stateVecReal[index]=stateVecReal[index]*renorm;
-
3770  stateVecImag[index]=stateVecImag[index]*renorm;
-
3771 
-
3772  stateVecReal[index+sizeHalfBlock]=0;
-
3773  stateVecImag[index+sizeHalfBlock]=0;
-
3774  }
-
3775  } else {
-
3776  // measure qubit is 1
-
3777 # ifdef _OPENMP
-
3778 # pragma omp for schedule (static)
-
3779 # endif
-
3780  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3781  thisBlock = thisTask / sizeHalfBlock;
-
3782  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3783  stateVecReal[index]=0;
-
3784  stateVecImag[index]=0;
-
3785 
-
3786  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
3787  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
3788  }
-
3789  }
-
3790  }
-
3791 
-
3792 }
+
3618  // clear outcomeProbs (in parallel, in case it's large)
+
3619  long long int numOutcomeProbs = (1 << numQubits);
+
3620  long long int j;
+
3621 
+
3622 # ifdef _OPENMP
+
3623 # pragma omp parallel \
+
3624  default (none) \
+
3625  shared (numOutcomeProbs,outcomeProbs) \
+
3626  private (j)
+
3627 # endif
+
3628  {
+
3629 # ifdef _OPENMP
+
3630 # pragma omp for schedule (static)
+
3631 # endif
+
3632  for (j=0; j<numOutcomeProbs; j++)
+
3633  outcomeProbs[j] = 0;
+
3634  }
+
3635 
+
3636  // compute first local index containing a diagonal element
+
3637  long long int localNumAmps = qureg.numAmpsPerChunk;
+
3638  long long int densityDim = (1LL << qureg.numQubitsRepresented);
+
3639  long long int diagSpacing = 1LL + densityDim;
+
3640  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
+
3641  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
+
3642  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
3643  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
+
3644 
+
3645  // computes how many diagonals are contained in this chunk
+
3646  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
+
3647  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
+
3648  numDiagsInThisChunk -= 1;
+
3649 
+
3650  long long int visitedDiags; // number of visited diagonals in this chunk so far
+
3651  long long int basisStateInd; // current diagonal index being considered
+
3652  long long int index; // index in the local chunk
+
3653 
+
3654  int q;
+
3655  long long int outcomeInd;
+
3656  qreal *stateRe = qureg.stateVec.real;
+
3657 
+
3658 # ifdef _OPENMP
+
3659 # pragma omp parallel \
+
3660  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateRe, numDiagsInThisChunk, qubits,numQubits, outcomeProbs) \
+
3661  private (visitedDiags, basisStateInd, index, q,outcomeInd)
+
3662 # endif
+
3663  {
+
3664 # ifdef _OPENMP
+
3665 # pragma omp for schedule (static)
+
3666 # endif
+
3667  // sums the diagonal elems of the density matrix where measureQubit=0
+
3668  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
+
3669 
+
3670  basisStateInd = numPrevDiags + visitedDiags;
+
3671  index = localIndNextDiag + diagSpacing * visitedDiags;
+
3672 
+
3673  // determine outcome implied by basisStateInd
+
3674  outcomeInd = 0;
+
3675  for (q=0; q<numQubits; q++)
+
3676  outcomeInd += extractBit(qubits[q], basisStateInd) * (1LL << q);
+
3677 
+
3678  // atomicly update corresponding outcome array element
+
3679  # ifdef _OPENMP
+
3680  # pragma omp atomic
+
3681  # endif
+
3682  outcomeProbs[outcomeInd] += stateRe[index];
+
3683  }
+
3684  }
+
3685 }
+
3686 
+
3687 void statevec_controlledPhaseFlip (Qureg qureg, int idQubit1, int idQubit2)
+
3688 {
+
3689  long long int index;
+
3690  long long int stateVecSize;
+
3691  int bit1, bit2;
+
3692 
+
3693  long long int chunkSize=qureg.numAmpsPerChunk;
+
3694  long long int chunkId=qureg.chunkId;
+
3695 
+
3696  // dimension of the state vector
+
3697  stateVecSize = qureg.numAmpsPerChunk;
+
3698  qreal *stateVecReal = qureg.stateVec.real;
+
3699  qreal *stateVecImag = qureg.stateVec.imag;
+
3700 
+
3701 # ifdef _OPENMP
+
3702 # pragma omp parallel for \
+
3703  default (none) \
+
3704  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
+
3705  private (index,bit1,bit2) \
+
3706  schedule (static)
+
3707 # endif
+
3708  for (index=0; index<stateVecSize; index++) {
+
3709  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
+
3710  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
+
3711  if (bit1 && bit2) {
+
3712  stateVecReal [index] = - stateVecReal [index];
+
3713  stateVecImag [index] = - stateVecImag [index];
+
3714  }
+
3715  }
+
3716 }
+
3717 
+
3718 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
+
3719 {
+
3720  long long int index;
+
3721  long long int stateVecSize;
+
3722 
+
3723  long long int chunkSize=qureg.numAmpsPerChunk;
+
3724  long long int chunkId=qureg.chunkId;
+
3725 
+
3726  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
3727 
+
3728  stateVecSize = qureg.numAmpsPerChunk;
+
3729  qreal *stateVecReal = qureg.stateVec.real;
+
3730  qreal *stateVecImag = qureg.stateVec.imag;
+
3731 
+
3732 # ifdef _OPENMP
+
3733 # pragma omp parallel \
+
3734  default (none) \
+
3735  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
+
3736  private (index)
+
3737 # endif
+
3738  {
+
3739 # ifdef _OPENMP
+
3740 # pragma omp for schedule (static)
+
3741 # endif
+
3742  for (index=0; index<stateVecSize; index++) {
+
3743  if (mask == (mask & (index+chunkId*chunkSize)) ){
+
3744  stateVecReal [index] = - stateVecReal [index];
+
3745  stateVecImag [index] = - stateVecImag [index];
+
3746  }
+
3747  }
+
3748  }
+
3749 }
+
3750 
+
3767 void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
+
3768 {
+
3769  // ----- sizes
+
3770  long long int sizeBlock, // size of blocks
+
3771  sizeHalfBlock; // size of blocks halved
+
3772  // ----- indices
+
3773  long long int thisBlock, // current block
+
3774  index; // current index for first half block
+
3775  // ----- measured probability
+
3776  qreal renorm; // probability (returned) value
+
3777  // ----- temp variables
+
3778  long long int thisTask; // task based approach for expose loop with small granularity
+
3779  // (good for shared memory parallelism)
+
3780  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3781 
+
3782  // ---------------------------------------------------------------- //
+
3783  // dimensions //
+
3784  // ---------------------------------------------------------------- //
+
3785  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
3786  // and then the number to skip
+
3787  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
3788 
+
3789  renorm=1/sqrt(totalProbability);
+
3790  qreal *stateVecReal = qureg.stateVec.real;
+
3791  qreal *stateVecImag = qureg.stateVec.imag;
+
3792 
3793 
-
3809 void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg, int measureQubit, qreal totalProbability)
-
3810 {
-
3811  // ----- temp variables
-
3812  long long int thisTask;
-
3813  long long int numTasks=qureg.numAmpsPerChunk;
-
3814 
-
3815  qreal renorm=1/sqrt(totalProbability);
-
3816 
-
3817  qreal *stateVecReal = qureg.stateVec.real;
-
3818  qreal *stateVecImag = qureg.stateVec.imag;
-
3819 
-
3820 # ifdef _OPENMP
-
3821 # pragma omp parallel \
-
3822  shared (numTasks,stateVecReal,stateVecImag) \
-
3823  private (thisTask)
-
3824 # endif
-
3825  {
-
3826 # ifdef _OPENMP
-
3827 # pragma omp for schedule (static)
-
3828 # endif
-
3829  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3830  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
-
3831  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
-
3832  }
-
3833  }
-
3834 }
-
3835 
-
3836 /* Set all amplitudes in one chunk to 0.
-
3837  * Measure in Zero performs an irreversible change to the state vector: it updates the vector according
-
3838  * to the event that a zero have been measured on the qubit indicated by measureQubit (where
-
3839  * this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and
-
3840  * then renormalising based on the total probability of measuring measureQubit=0 or 1.
-
3841  * In the distributed version, one block (with measureQubit=0 in the first half of the block and
-
3842  * measureQubit=1 in the second half of the block) is spread over multiple chunks, meaning that each chunks performs
-
3843  * only renormalisation or only setting amplitudes to 0. This function handles setting amplitudes to 0.
-
3844  *
-
3845  * @param[in,out] qureg object representing the set of qubits
-
3846  */
- -
3848 {
-
3849  // ----- temp variables
-
3850  long long int thisTask;
-
3851  long long int numTasks=qureg.numAmpsPerChunk;
-
3852 
-
3853  // ---------------------------------------------------------------- //
-
3854  // find probability //
-
3855  // ---------------------------------------------------------------- //
+
3794 # ifdef _OPENMP
+
3795 # pragma omp parallel \
+
3796  default (none) \
+
3797  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
+
3798  private (thisTask,thisBlock,index)
+
3799 # endif
+
3800  {
+
3801  if (outcome==0){
+
3802  // measure qubit is 0
+
3803 # ifdef _OPENMP
+
3804 # pragma omp for schedule (static)
+
3805 # endif
+
3806  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3807  thisBlock = thisTask / sizeHalfBlock;
+
3808  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3809  stateVecReal[index]=stateVecReal[index]*renorm;
+
3810  stateVecImag[index]=stateVecImag[index]*renorm;
+
3811 
+
3812  stateVecReal[index+sizeHalfBlock]=0;
+
3813  stateVecImag[index+sizeHalfBlock]=0;
+
3814  }
+
3815  } else {
+
3816  // measure qubit is 1
+
3817 # ifdef _OPENMP
+
3818 # pragma omp for schedule (static)
+
3819 # endif
+
3820  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3821  thisBlock = thisTask / sizeHalfBlock;
+
3822  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3823  stateVecReal[index]=0;
+
3824  stateVecImag[index]=0;
+
3825 
+
3826  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
+
3827  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
+
3828  }
+
3829  }
+
3830  }
+
3831 
+
3832 }
+
3833 
+
3849 void statevec_collapseToKnownProbOutcomeDistributedRenorm (Qureg qureg, int measureQubit, qreal totalProbability)
+
3850 {
+
3851  // ----- temp variables
+
3852  long long int thisTask;
+
3853  long long int numTasks=qureg.numAmpsPerChunk;
+
3854 
+
3855  qreal renorm=1/sqrt(totalProbability);
3856 
3857  qreal *stateVecReal = qureg.stateVec.real;
3858  qreal *stateVecImag = qureg.stateVec.imag;
@@ -3746,860 +3746,899 @@
3867 # pragma omp for schedule (static)
3868 # endif
3869  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3870  stateVecReal[thisTask] = 0;
-
3871  stateVecImag[thisTask] = 0;
+
3870  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
+
3871  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
3872  }
3873  }
3874 }
3875 
-
3882 void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2) {
-
3883 
-
3884  // can't use qureg.stateVec as a private OMP var
-
3885  qreal *reVec = qureg.stateVec.real;
-
3886  qreal *imVec = qureg.stateVec.imag;
-
3887 
-
3888  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
3889  long long int thisTask;
-
3890  long long int ind00, ind01, ind10;
-
3891  qreal re01, re10;
-
3892  qreal im01, im10;
-
3893 
-
3894 # ifdef _OPENMP
-
3895 # pragma omp parallel \
-
3896  default (none) \
-
3897  shared (reVec,imVec,numTasks,qb1,qb2) \
-
3898  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
-
3899 # endif
-
3900  {
-
3901 # ifdef _OPENMP
-
3902 # pragma omp for schedule (static)
-
3903 # endif
-
3904  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3905  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
3906  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
3907  ind01 = flipBit(ind00, qb1);
-
3908  ind10 = flipBit(ind00, qb2);
-
3909 
-
3910  // extract statevec amplitudes
-
3911  re01 = reVec[ind01]; im01 = imVec[ind01];
-
3912  re10 = reVec[ind10]; im10 = imVec[ind10];
-
3913 
-
3914  // swap 01 and 10 amps
-
3915  reVec[ind01] = re10; reVec[ind10] = re01;
-
3916  imVec[ind01] = im10; imVec[ind10] = im01;
-
3917  }
-
3918  }
-
3919 }
-
3920 
-
3925 void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2) {
-
3926 
-
3927  // can't use qureg.stateVec as a private OMP var
-
3928  qreal *reVec = qureg.stateVec.real;
-
3929  qreal *imVec = qureg.stateVec.imag;
-
3930  qreal *rePairVec = qureg.pairStateVec.real;
-
3931  qreal *imPairVec = qureg.pairStateVec.imag;
-
3932 
-
3933  long long int numLocalAmps = qureg.numAmpsPerChunk;
-
3934  long long int globalStartInd = qureg.chunkId * numLocalAmps;
-
3935  long long int pairGlobalStartInd = pairRank * numLocalAmps;
-
3936 
-
3937  long long int localInd, globalInd;
-
3938  long long int pairLocalInd, pairGlobalInd;
-
3939 
-
3940 # ifdef _OPENMP
-
3941 # pragma omp parallel \
-
3942  default (none) \
-
3943  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
-
3944  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
-
3945 # endif
-
3946  {
-
3947 # ifdef _OPENMP
-
3948 # pragma omp for schedule (static)
-
3949 # endif
-
3950  for (localInd=0; localInd < numLocalAmps; localInd++) {
-
3951 
-
3952  globalInd = globalStartInd + localInd;
-
3953  if (isOddParity(globalInd, qb1, qb2)) {
-
3954 
-
3955  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
-
3956  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
-
3957 
-
3958  reVec[localInd] = rePairVec[pairLocalInd];
-
3959  imVec[localInd] = imPairVec[pairLocalInd];
-
3960  }
-
3961  }
-
3962  }
-
3963 }
-
3964 
-
3965 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
-
3966 
-
3967  long long int numAmps = qureg1.numAmpsPerChunk;
-
3968 
-
3969  qreal *vecRe1 = qureg1.stateVec.real;
-
3970  qreal *vecIm1 = qureg1.stateVec.imag;
-
3971  qreal *vecRe2 = qureg2.stateVec.real;
-
3972  qreal *vecIm2 = qureg2.stateVec.imag;
-
3973  qreal *vecReOut = out.stateVec.real;
-
3974  qreal *vecImOut = out.stateVec.imag;
-
3975 
-
3976  qreal facRe1 = fac1.real;
-
3977  qreal facIm1 = fac1.imag;
-
3978  qreal facRe2 = fac2.real;
-
3979  qreal facIm2 = fac2.imag;
-
3980  qreal facReOut = facOut.real;
-
3981  qreal facImOut = facOut.imag;
-
3982 
-
3983  qreal re1,im1, re2,im2, reOut,imOut;
-
3984  long long int index;
-
3985 
-
3986 # ifdef _OPENMP
-
3987 # pragma omp parallel \
-
3988  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
-
3989  private (index, re1,im1, re2,im2, reOut,imOut)
-
3990 # endif
-
3991  {
-
3992 # ifdef _OPENMP
-
3993 # pragma omp for schedule (static)
-
3994 # endif
-
3995  for (index=0LL; index<numAmps; index++) {
-
3996  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3997  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3998  reOut = vecReOut[index];
-
3999  imOut = vecImOut[index];
-
4000 
-
4001  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
4002  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
4003  }
-
4004  }
-
4005 }
+
3876 /* Set all amplitudes in one chunk to 0.
+
3877  * Measure in Zero performs an irreversible change to the state vector: it updates the vector according
+
3878  * to the event that a zero have been measured on the qubit indicated by measureQubit (where
+
3879  * this label starts from 0, of course). It achieves this by setting all inconsistent amplitudes to 0 and
+
3880  * then renormalising based on the total probability of measuring measureQubit=0 or 1.
+
3881  * In the distributed version, one block (with measureQubit=0 in the first half of the block and
+
3882  * measureQubit=1 in the second half of the block) is spread over multiple chunks, meaning that each chunks performs
+
3883  * only renormalisation or only setting amplitudes to 0. This function handles setting amplitudes to 0.
+
3884  *
+
3885  * @param[in,out] qureg object representing the set of qubits
+
3886  */
+ +
3888 {
+
3889  // ----- temp variables
+
3890  long long int thisTask;
+
3891  long long int numTasks=qureg.numAmpsPerChunk;
+
3892 
+
3893  // ---------------------------------------------------------------- //
+
3894  // find probability //
+
3895  // ---------------------------------------------------------------- //
+
3896 
+
3897  qreal *stateVecReal = qureg.stateVec.real;
+
3898  qreal *stateVecImag = qureg.stateVec.imag;
+
3899 
+
3900 # ifdef _OPENMP
+
3901 # pragma omp parallel \
+
3902  shared (numTasks,stateVecReal,stateVecImag) \
+
3903  private (thisTask)
+
3904 # endif
+
3905  {
+
3906 # ifdef _OPENMP
+
3907 # pragma omp for schedule (static)
+
3908 # endif
+
3909  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3910  stateVecReal[thisTask] = 0;
+
3911  stateVecImag[thisTask] = 0;
+
3912  }
+
3913  }
+
3914 }
+
3915 
+
3922 void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2) {
+
3923 
+
3924  // can't use qureg.stateVec as a private OMP var
+
3925  qreal *reVec = qureg.stateVec.real;
+
3926  qreal *imVec = qureg.stateVec.imag;
+
3927 
+
3928  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
+
3929  long long int thisTask;
+
3930  long long int ind00, ind01, ind10;
+
3931  qreal re01, re10;
+
3932  qreal im01, im10;
+
3933 
+
3934 # ifdef _OPENMP
+
3935 # pragma omp parallel \
+
3936  default (none) \
+
3937  shared (reVec,imVec,numTasks,qb1,qb2) \
+
3938  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
+
3939 # endif
+
3940  {
+
3941 # ifdef _OPENMP
+
3942 # pragma omp for schedule (static)
+
3943 # endif
+
3944  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3945  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
+
3946  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
+
3947  ind01 = flipBit(ind00, qb1);
+
3948  ind10 = flipBit(ind00, qb2);
+
3949 
+
3950  // extract statevec amplitudes
+
3951  re01 = reVec[ind01]; im01 = imVec[ind01];
+
3952  re10 = reVec[ind10]; im10 = imVec[ind10];
+
3953 
+
3954  // swap 01 and 10 amps
+
3955  reVec[ind01] = re10; reVec[ind10] = re01;
+
3956  imVec[ind01] = im10; imVec[ind10] = im01;
+
3957  }
+
3958  }
+
3959 }
+
3960 
+
3965 void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2) {
+
3966 
+
3967  // can't use qureg.stateVec as a private OMP var
+
3968  qreal *reVec = qureg.stateVec.real;
+
3969  qreal *imVec = qureg.stateVec.imag;
+
3970  qreal *rePairVec = qureg.pairStateVec.real;
+
3971  qreal *imPairVec = qureg.pairStateVec.imag;
+
3972 
+
3973  long long int numLocalAmps = qureg.numAmpsPerChunk;
+
3974  long long int globalStartInd = qureg.chunkId * numLocalAmps;
+
3975  long long int pairGlobalStartInd = pairRank * numLocalAmps;
+
3976 
+
3977  long long int localInd, globalInd;
+
3978  long long int pairLocalInd, pairGlobalInd;
+
3979 
+
3980 # ifdef _OPENMP
+
3981 # pragma omp parallel \
+
3982  default (none) \
+
3983  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
+
3984  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
+
3985 # endif
+
3986  {
+
3987 # ifdef _OPENMP
+
3988 # pragma omp for schedule (static)
+
3989 # endif
+
3990  for (localInd=0; localInd < numLocalAmps; localInd++) {
+
3991 
+
3992  globalInd = globalStartInd + localInd;
+
3993  if (isOddParity(globalInd, qb1, qb2)) {
+
3994 
+
3995  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
+
3996  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
+
3997 
+
3998  reVec[localInd] = rePairVec[pairLocalInd];
+
3999  imVec[localInd] = imPairVec[pairLocalInd];
+
4000  }
+
4001  }
+
4002  }
+
4003 }
+
4004 
+
4005 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
4006 
- +
4007  long long int numAmps = qureg1.numAmpsPerChunk;
4008 
-
4009  // each node/chunk modifies only its values in an embarrassingly parallelisable way
-
4010  long long int numAmps = qureg.numAmpsPerChunk;
-
4011 
-
4012  qreal* stateRe = qureg.stateVec.real;
-
4013  qreal* stateIm = qureg.stateVec.imag;
-
4014  qreal* opRe = op.real;
-
4015  qreal* opIm = op.imag;
-
4016 
-
4017  qreal a,b,c,d;
-
4018  long long int index;
-
4019 
-
4020 # ifdef _OPENMP
-
4021 # pragma omp parallel \
-
4022  shared (stateRe,stateIm, opRe,opIm, numAmps) \
-
4023  private (index, a,b,c,d)
-
4024 # endif
-
4025  {
+
4009  qreal *vecRe1 = qureg1.stateVec.real;
+
4010  qreal *vecIm1 = qureg1.stateVec.imag;
+
4011  qreal *vecRe2 = qureg2.stateVec.real;
+
4012  qreal *vecIm2 = qureg2.stateVec.imag;
+
4013  qreal *vecReOut = out.stateVec.real;
+
4014  qreal *vecImOut = out.stateVec.imag;
+
4015 
+
4016  qreal facRe1 = fac1.real;
+
4017  qreal facIm1 = fac1.imag;
+
4018  qreal facRe2 = fac2.real;
+
4019  qreal facIm2 = fac2.imag;
+
4020  qreal facReOut = facOut.real;
+
4021  qreal facImOut = facOut.imag;
+
4022 
+
4023  qreal re1,im1, re2,im2, reOut,imOut;
+
4024  long long int index;
+
4025 
4026 # ifdef _OPENMP
-
4027 # pragma omp for schedule (static)
-
4028 # endif
-
4029  for (index=0LL; index<numAmps; index++) {
-
4030  a = stateRe[index];
-
4031  b = stateIm[index];
-
4032  c = opRe[index];
-
4033  d = opIm[index];
-
4034 
-
4035  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
4036  stateRe[index] = a*c - b*d;
-
4037  stateIm[index] = a*d + b*c;
-
4038  }
-
4039  }
-
4040 }
-
4041 
- -
4043 
-
4044  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
-
4045  * Furthermore, since it's gauranteed each node contains an integer number of
-
4046  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
-
4047  * then we know iteration below begins at the 'top' of a column, and there is
-
4048  * no offset for op (pairStateVector)
-
4049  */
-
4050 
-
4051  long long int numAmps = qureg.numAmpsPerChunk;
-
4052  int opDim = (1 << op.numQubits);
-
4053 
-
4054  qreal* stateRe = qureg.stateVec.real;
-
4055  qreal* stateIm = qureg.stateVec.imag;
-
4056  qreal* opRe = qureg.pairStateVec.real;
-
4057  qreal* opIm = qureg.pairStateVec.imag;
-
4058 
-
4059  qreal a,b,c,d;
-
4060  long long int index;
-
4061 
-
4062 # ifdef _OPENMP
-
4063 # pragma omp parallel \
-
4064  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
-
4065  private (index, a,b,c,d)
-
4066 # endif
-
4067  {
-
4068 # ifdef _OPENMP
-
4069 # pragma omp for schedule (static)
-
4070 # endif
-
4071  for (index=0LL; index<numAmps; index++) {
-
4072  a = stateRe[index];
-
4073  b = stateIm[index];
-
4074  c = opRe[index % opDim];
-
4075  d = opIm[index % opDim];
-
4076 
-
4077  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
4078  stateRe[index] = a*c - b*d;
-
4079  stateIm[index] = a*d + b*c;
-
4080  }
-
4081  }
-
4082 }
-
4083 
- -
4085 
-
4086  qreal expecRe = 0;
-
4087  qreal expecIm = 0;
-
4088 
-
4089  long long int index;
-
4090  long long int numAmps = qureg.numAmpsPerChunk;
-
4091  qreal *stateReal = qureg.stateVec.real;
-
4092  qreal *stateImag = qureg.stateVec.imag;
-
4093  qreal *opReal = op.real;
-
4094  qreal *opImag = op.imag;
-
4095 
-
4096  qreal vecRe,vecIm,vecAbs, opRe, opIm;
-
4097 
-
4098 # ifdef _OPENMP
-
4099 # pragma omp parallel \
-
4100  shared (stateReal, stateImag, opReal, opImag, numAmps) \
-
4101  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
-
4102  reduction ( +:expecRe, expecIm )
-
4103 # endif
-
4104  {
-
4105 # ifdef _OPENMP
-
4106 # pragma omp for schedule (static)
-
4107 # endif
-
4108  for (index=0; index < numAmps; index++) {
-
4109  vecRe = stateReal[index];
-
4110  vecIm = stateImag[index];
-
4111  opRe = opReal[index];
-
4112  opIm = opImag[index];
-
4113 
-
4114  // abs(vec)^2 op
-
4115  vecAbs = vecRe*vecRe + vecIm*vecIm;
-
4116  expecRe += vecAbs*opRe;
-
4117  expecIm += vecAbs*opIm;
-
4118  }
-
4119  }
-
4120 
-
4121  Complex innerProd;
-
4122  innerProd.real = expecRe;
-
4123  innerProd.imag = expecIm;
-
4124  return innerProd;
-
4125 }
-
4126 
- +
4027 # pragma omp parallel \
+
4028  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
+
4029  private (index, re1,im1, re2,im2, reOut,imOut)
+
4030 # endif
+
4031  {
+
4032 # ifdef _OPENMP
+
4033 # pragma omp for schedule (static)
+
4034 # endif
+
4035  for (index=0LL; index<numAmps; index++) {
+
4036  re1 = vecRe1[index]; im1 = vecIm1[index];
+
4037  re2 = vecRe2[index]; im2 = vecIm2[index];
+
4038  reOut = vecReOut[index];
+
4039  imOut = vecImOut[index];
+
4040 
+
4041  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
+
4042  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
+
4043  }
+
4044  }
+
4045 }
+
4046 
+ +
4048 
+
4049  // each node/chunk modifies only its values in an embarrassingly parallelisable way
+
4050  long long int numAmps = qureg.numAmpsPerChunk;
+
4051 
+
4052  qreal* stateRe = qureg.stateVec.real;
+
4053  qreal* stateIm = qureg.stateVec.imag;
+
4054  qreal* opRe = op.real;
+
4055  qreal* opIm = op.imag;
+
4056 
+
4057  qreal a,b,c,d;
+
4058  long long int index;
+
4059 
+
4060 # ifdef _OPENMP
+
4061 # pragma omp parallel \
+
4062  shared (stateRe,stateIm, opRe,opIm, numAmps) \
+
4063  private (index, a,b,c,d)
+
4064 # endif
+
4065  {
+
4066 # ifdef _OPENMP
+
4067 # pragma omp for schedule (static)
+
4068 # endif
+
4069  for (index=0LL; index<numAmps; index++) {
+
4070  a = stateRe[index];
+
4071  b = stateIm[index];
+
4072  c = opRe[index];
+
4073  d = opIm[index];
+
4074 
+
4075  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
4076  stateRe[index] = a*c - b*d;
+
4077  stateIm[index] = a*d + b*c;
+
4078  }
+
4079  }
+
4080 }
+
4081 
+ +
4083 
+
4084  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
+
4085  * Furthermore, since it's gauranteed each node contains an integer number of
+
4086  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
+
4087  * then we know iteration below begins at the 'top' of a column, and there is
+
4088  * no offset for op (pairStateVector)
+
4089  */
+
4090 
+
4091  long long int numAmps = qureg.numAmpsPerChunk;
+
4092  int opDim = (1 << op.numQubits);
+
4093 
+
4094  qreal* stateRe = qureg.stateVec.real;
+
4095  qreal* stateIm = qureg.stateVec.imag;
+
4096  qreal* opRe = qureg.pairStateVec.real;
+
4097  qreal* opIm = qureg.pairStateVec.imag;
+
4098 
+
4099  qreal a,b,c,d;
+
4100  long long int index;
+
4101 
+
4102 # ifdef _OPENMP
+
4103 # pragma omp parallel \
+
4104  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
+
4105  private (index, a,b,c,d)
+
4106 # endif
+
4107  {
+
4108 # ifdef _OPENMP
+
4109 # pragma omp for schedule (static)
+
4110 # endif
+
4111  for (index=0LL; index<numAmps; index++) {
+
4112  a = stateRe[index];
+
4113  b = stateIm[index];
+
4114  c = opRe[index % opDim];
+
4115  d = opIm[index % opDim];
+
4116 
+
4117  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
4118  stateRe[index] = a*c - b*d;
+
4119  stateIm[index] = a*d + b*c;
+
4120  }
+
4121  }
+
4122 }
+
4123 
+ +
4125 
+
4126  qreal expecRe = 0;
+
4127  qreal expecIm = 0;
4128 
-
4129  /* since for every 1 element in \p op, there exists a column in \p qureg,
-
4130  * we know that the elements in \p op live on the same node as the
-
4131  * corresponding diagonal elements of \p qureg. This means, the problem is
-
4132  * embarrassingly parallelisable, and the code below works for both
-
4133  * serial and distributed modes.
-
4134  */
+
4129  long long int index;
+
4130  long long int numAmps = qureg.numAmpsPerChunk;
+
4131  qreal *stateReal = qureg.stateVec.real;
+
4132  qreal *stateImag = qureg.stateVec.imag;
+
4133  qreal *opReal = op.real;
+
4134  qreal *opImag = op.imag;
4135 
-
4136  // computes first local index containing a diagonal element
-
4137  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
4138  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
4139  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
4140  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
4141  long long int numAmps = qureg.numAmpsPerChunk;
-
4142 
-
4143  qreal* stateReal = qureg.stateVec.real;
-
4144  qreal* stateImag = qureg.stateVec.imag;
-
4145  qreal* opReal = op.real;
-
4146  qreal* opImag = op.imag;
-
4147 
-
4148  qreal expecRe = 0;
-
4149  qreal expecIm = 0;
-
4150 
-
4151  long long int stateInd;
-
4152  long long int opInd;
-
4153  qreal matRe, matIm, opRe, opIm;
-
4154 
-
4155  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
-
4156 
-
4157 # ifdef _OPENMP
-
4158 # pragma omp parallel \
-
4159  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
-
4160  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
-
4161  reduction ( +:expecRe, expecIm )
-
4162 # endif
-
4163  {
-
4164 # ifdef _OPENMP
-
4165 # pragma omp for schedule (static)
-
4166 # endif
-
4167  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
-
4168 
-
4169  matRe = stateReal[stateInd];
-
4170  matIm = stateImag[stateInd];
-
4171  opInd = (stateInd - localIndNextDiag) / diagSpacing;
-
4172  opRe = opReal[opInd];
-
4173  opIm = opImag[opInd];
-
4174 
-
4175  // (matRe + matIm i)(opRe + opIm i) =
-
4176  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
4177  expecRe += matRe * opRe - matIm * opIm;
-
4178  expecIm += matRe * opIm + matIm * opRe;
-
4179  }
-
4180  }
-
4181 
-
4182  Complex expecVal;
-
4183  expecVal.real = expecRe;
-
4184  expecVal.imag = expecIm;
-
4185  return expecVal;
-
4186 }
-
4187 
-
4188 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
-
4189 
-
4190  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
4191  // these may be negative or above qureg.numAmpsPerChunk
-
4192  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
-
4193  long long int localEndInd = localStartInd + numElems; // exclusive
+
4136  qreal vecRe,vecIm,vecAbs, opRe, opIm;
+
4137 
+
4138 # ifdef _OPENMP
+
4139 # pragma omp parallel \
+
4140  shared (stateReal, stateImag, opReal, opImag, numAmps) \
+
4141  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
+
4142  reduction ( +:expecRe, expecIm )
+
4143 # endif
+
4144  {
+
4145 # ifdef _OPENMP
+
4146 # pragma omp for schedule (static)
+
4147 # endif
+
4148  for (index=0; index < numAmps; index++) {
+
4149  vecRe = stateReal[index];
+
4150  vecIm = stateImag[index];
+
4151  opRe = opReal[index];
+
4152  opIm = opImag[index];
+
4153 
+
4154  // abs(vec)^2 op
+
4155  vecAbs = vecRe*vecRe + vecIm*vecIm;
+
4156  expecRe += vecAbs*opRe;
+
4157  expecIm += vecAbs*opIm;
+
4158  }
+
4159  }
+
4160 
+
4161  Complex innerProd;
+
4162  innerProd.real = expecRe;
+
4163  innerProd.imag = expecIm;
+
4164  return innerProd;
+
4165 }
+
4166 
+ +
4168 
+
4169  /* since for every 1 element in \p op, there exists a column in \p qureg,
+
4170  * we know that the elements in \p op live on the same node as the
+
4171  * corresponding diagonal elements of \p qureg. This means, the problem is
+
4172  * embarrassingly parallelisable, and the code below works for both
+
4173  * serial and distributed modes.
+
4174  */
+
4175 
+
4176  // computes first local index containing a diagonal element
+
4177  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
+
4178  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
+
4179  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
4180  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
+
4181  long long int numAmps = qureg.numAmpsPerChunk;
+
4182 
+
4183  qreal* stateReal = qureg.stateVec.real;
+
4184  qreal* stateImag = qureg.stateVec.imag;
+
4185  qreal* opReal = op.real;
+
4186  qreal* opImag = op.imag;
+
4187 
+
4188  qreal expecRe = 0;
+
4189  qreal expecIm = 0;
+
4190 
+
4191  long long int stateInd;
+
4192  long long int opInd;
+
4193  qreal matRe, matIm, opRe, opIm;
4194 
-
4195  // add this to a local index to get corresponding elem in reals & imags
-
4196  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
-
4197 
-
4198  // restrict these indices to fit into this chunk
-
4199  if (localStartInd < 0)
-
4200  localStartInd = 0;
-
4201  if (localEndInd > op.numElemsPerChunk)
-
4202  localEndInd = op.numElemsPerChunk;
-
4203  // they may now be out of order = no iterations
-
4204 
-
4205  // unpacking OpenMP vars
-
4206  long long int index;
-
4207  qreal* vecRe = op.real;
-
4208  qreal* vecIm = op.imag;
-
4209 
-
4210 # ifdef _OPENMP
-
4211 # pragma omp parallel \
-
4212  default (none) \
-
4213  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
-
4214  private (index)
-
4215 # endif
-
4216  {
-
4217 # ifdef _OPENMP
-
4218 # pragma omp for schedule (static)
-
4219 # endif
-
4220  // iterate these local inds - this might involve no iterations
-
4221  for (index=localStartInd; index < localEndInd; index++) {
-
4222  vecRe[index] = real[index + offset];
-
4223  vecIm[index] = imag[index + offset];
-
4224  }
-
4225  }
+
4195  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
+
4196 
+
4197 # ifdef _OPENMP
+
4198 # pragma omp parallel \
+
4199  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
+
4200  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
+
4201  reduction ( +:expecRe, expecIm )
+
4202 # endif
+
4203  {
+
4204 # ifdef _OPENMP
+
4205 # pragma omp for schedule (static)
+
4206 # endif
+
4207  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
+
4208 
+
4209  matRe = stateReal[stateInd];
+
4210  matIm = stateImag[stateInd];
+
4211  opInd = (stateInd - localIndNextDiag) / diagSpacing;
+
4212  opRe = opReal[opInd];
+
4213  opIm = opImag[opInd];
+
4214 
+
4215  // (matRe + matIm i)(opRe + opIm i) =
+
4216  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
+
4217  expecRe += matRe * opRe - matIm * opIm;
+
4218  expecIm += matRe * opIm + matIm * opRe;
+
4219  }
+
4220  }
+
4221 
+
4222  Complex expecVal;
+
4223  expecVal.real = expecRe;
+
4224  expecVal.imag = expecIm;
+
4225  return expecVal;
4226 }
4227 
- -
4229  Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding,
-
4230  qreal* coeffs, qreal* exponents, int numTerms,
-
4231  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
4232  int conj)
-
4233 {
-
4234  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4235 
-
4236  // thread shared vars
-
4237  int chunkId = qureg.chunkId;
-
4238  long long int numAmps = qureg.numAmpsPerChunk;
-
4239  qreal* stateRe = qureg.stateVec.real;
-
4240  qreal* stateIm = qureg.stateVec.imag;
-
4241 
-
4242  // thread private vars
-
4243  long long int index, globalAmpInd, phaseInd;
-
4244  int i, t, q;
-
4245  qreal phase, c, s, re, im;
-
4246 
-
4247 # ifdef _OPENMP
-
4248 # pragma omp parallel \
-
4249  default (none) \
-
4250  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubits,encoding, coeffs,exponents,numTerms, overrideInds,overridePhases,numOverrides, conj) \
-
4251  private (index, globalAmpInd, phaseInd, i,t,q, phase, c,s,re,im)
-
4252 # endif
-
4253  {
-
4254 # ifdef _OPENMP
-
4255 # pragma omp for schedule (static)
-
4256 # endif
-
4257  for (index=0LL; index<numAmps; index++) {
-
4258 
-
4259  // determine global amplitude index
-
4260  globalAmpInd = chunkId * numAmps + index;
-
4261 
-
4262  // determine phase index of {qubits}
-
4263  phaseInd = 0LL;
-
4264  if (encoding == UNSIGNED) {
-
4265  for (q=0; q<numQubits; q++) // use significance order specified by {qubits}
-
4266  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
4267  }
-
4268  else if (encoding == TWOS_COMPLEMENT) {
-
4269  for (q=0; q<numQubits-1; q++) // use final qubit to indicate sign
-
4270  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
4271  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
-
4272  phaseInd -= (1LL << (numQubits-1));
-
4273  }
-
4274 
-
4275  // determine if this phase index has an overriden value (i < numOverrides)
-
4276  for (i=0; i<numOverrides; i++)
-
4277  if (phaseInd == overrideInds[i])
-
4278  break;
-
4279 
-
4280  // determine phase from {coeffs}, {exponents} (unless overriden)
-
4281  phase = 0;
-
4282  if (i < numOverrides)
-
4283  phase = overridePhases[i];
-
4284  else
-
4285  for (t=0; t<numTerms; t++)
-
4286  phase += coeffs[t] * pow(phaseInd, exponents[t]);
-
4287 
-
4288  // negate phase to conjugate operator
-
4289  if (conj)
-
4290  phase *= -1;
-
4291 
-
4292  // modify amp to amp * exp(i phase)
-
4293  c = cos(phase);
-
4294  s = sin(phase);
-
4295  re = stateRe[index];
-
4296  im = stateIm[index];
-
4297 
-
4298  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4299  stateRe[index] = re*c - im*s;
-
4300  stateIm[index] = re*s + im*c;
-
4301  }
-
4302  }
-
4303 }
-
4304 
- -
4306  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
-
4307  qreal* coeffs, qreal* exponents, int* numTermsPerReg,
-
4308  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
4309  int conj)
-
4310 {
-
4311  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4312 
-
4313  // note partitions of qubits, coeffs, exponents and overrideInds are stored flat
+
4228 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
+
4229 
+
4230  // local start/end indices of the given amplitudes, assuming they fit in this chunk
+
4231  // these may be negative or above qureg.numAmpsPerChunk
+
4232  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
+
4233  long long int localEndInd = localStartInd + numElems; // exclusive
+
4234 
+
4235  // add this to a local index to get corresponding elem in reals & imags
+
4236  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
+
4237 
+
4238  // restrict these indices to fit into this chunk
+
4239  if (localStartInd < 0)
+
4240  localStartInd = 0;
+
4241  if (localEndInd > op.numElemsPerChunk)
+
4242  localEndInd = op.numElemsPerChunk;
+
4243  // they may now be out of order = no iterations
+
4244 
+
4245  // unpacking OpenMP vars
+
4246  long long int index;
+
4247  qreal* vecRe = op.real;
+
4248  qreal* vecIm = op.imag;
+
4249 
+
4250 # ifdef _OPENMP
+
4251 # pragma omp parallel \
+
4252  default (none) \
+
4253  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
+
4254  private (index)
+
4255 # endif
+
4256  {
+
4257 # ifdef _OPENMP
+
4258 # pragma omp for schedule (static)
+
4259 # endif
+
4260  // iterate these local inds - this might involve no iterations
+
4261  for (index=localStartInd; index < localEndInd; index++) {
+
4262  vecRe[index] = real[index + offset];
+
4263  vecIm[index] = imag[index + offset];
+
4264  }
+
4265  }
+
4266 }
+
4267 
+ +
4269  Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding,
+
4270  qreal* coeffs, qreal* exponents, int numTerms,
+
4271  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
4272  int conj)
+
4273 {
+
4274  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4275 
+
4276  // thread shared vars
+
4277  int chunkId = qureg.chunkId;
+
4278  long long int numAmps = qureg.numAmpsPerChunk;
+
4279  qreal* stateRe = qureg.stateVec.real;
+
4280  qreal* stateIm = qureg.stateVec.imag;
+
4281 
+
4282  // thread private vars
+
4283  long long int index, globalAmpInd, phaseInd;
+
4284  int i, t, q;
+
4285  qreal phase, c, s, re, im;
+
4286 
+
4287 # ifdef _OPENMP
+
4288 # pragma omp parallel \
+
4289  default (none) \
+
4290  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubits,encoding, coeffs,exponents,numTerms, overrideInds,overridePhases,numOverrides, conj) \
+
4291  private (index, globalAmpInd, phaseInd, i,t,q, phase, c,s,re,im)
+
4292 # endif
+
4293  {
+
4294 # ifdef _OPENMP
+
4295 # pragma omp for schedule (static)
+
4296 # endif
+
4297  for (index=0LL; index<numAmps; index++) {
+
4298 
+
4299  // determine global amplitude index
+
4300  globalAmpInd = chunkId * numAmps + index;
+
4301 
+
4302  // determine phase index of {qubits}
+
4303  phaseInd = 0LL;
+
4304  if (encoding == UNSIGNED) {
+
4305  for (q=0; q<numQubits; q++) // use significance order specified by {qubits}
+
4306  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
4307  }
+
4308  else if (encoding == TWOS_COMPLEMENT) {
+
4309  for (q=0; q<numQubits-1; q++) // use final qubit to indicate sign
+
4310  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
4311  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
+
4312  phaseInd -= (1LL << (numQubits-1));
+
4313  }
4314 
-
4315  // thread-shared vaes
-
4316  int chunkId = qureg.chunkId;
-
4317  long long int numAmps = qureg.numAmpsPerChunk;
-
4318  qreal* stateRe = qureg.stateVec.real;
-
4319  qreal* stateIm = qureg.stateVec.imag;
-
4320 
-
4321  // thread-private vars
-
4322  long long int index, globalAmpInd;
-
4323  int r, q, i, t, found, flatInd;
-
4324  qreal phase, c, s, re, im;
-
4325 
-
4326  // each thread has a private static array of length >= numRegs (private var-length is illegal)
-
4327  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
-
4328 
-
4329 # ifdef _OPENMP
-
4330 # pragma omp parallel \
-
4331  default (none) \
-
4332  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, coeffs,exponents,numTermsPerReg, overrideInds,overridePhases,numOverrides, conj) \
-
4333  private (index,globalAmpInd, r,q,i,t,flatInd, found, phaseInds,phase, c,s,re,im)
-
4334 # endif
-
4335  {
-
4336 # ifdef _OPENMP
-
4337 # pragma omp for schedule (static)
-
4338 # endif
-
4339  for (index=0LL; index<numAmps; index++) {
-
4340 
-
4341  // determine global amplitude index
-
4342  globalAmpInd = chunkId * numAmps + index;
-
4343 
-
4344  // determine phase indices
-
4345  flatInd = 0;
-
4346  for (r=0; r<numRegs; r++) {
-
4347  phaseInds[r] = 0LL;
-
4348 
-
4349  if (encoding == UNSIGNED) {
-
4350  for (q=0; q<numQubitsPerReg[r]; q++)
-
4351  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
-
4352  }
-
4353  else if (encoding == TWOS_COMPLEMENT) {
-
4354  for (q=0; q<numQubitsPerReg[r]-1; q++)
-
4355  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
4356  // use final qubit to indicate sign
-
4357  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
4358  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
-
4359  }
-
4360  }
-
4361 
-
4362  // determine if this phase index has an overriden value (i < numOverrides)
-
4363  for (i=0; i<numOverrides; i++) {
-
4364  found = 1;
-
4365  for (r=0; r<numRegs; r++) {
-
4366  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
-
4367  found = 0;
-
4368  break;
-
4369  }
-
4370  }
-
4371  if (found)
-
4372  break;
-
4373  }
-
4374 
-
4375  // compute the phase (unless overriden)
-
4376  phase = 0;
-
4377  if (i < numOverrides)
-
4378  phase = overridePhases[i];
-
4379  else {
-
4380  flatInd = 0;
-
4381  for (r=0; r<numRegs; r++) {
-
4382  for (t=0; t<numTermsPerReg[r]; t++) {
-
4383  phase += coeffs[flatInd] * pow(phaseInds[r], exponents[flatInd]);
-
4384  flatInd++;
-
4385  }
-
4386  }
-
4387  }
-
4388 
-
4389  // negate phase to conjugate operator
-
4390  if (conj)
-
4391  phase *= -1;
-
4392 
-
4393  // modify amp to amp * exp(i phase)
-
4394  c = cos(phase);
-
4395  s = sin(phase);
-
4396  re = stateRe[index];
-
4397  im = stateIm[index];
-
4398 
-
4399  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4400  stateRe[index] = re*c - im*s;
-
4401  stateIm[index] = re*s + im*c;
-
4402  }
-
4403  }
-
4404 }
-
4405 
- -
4407  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
-
4408  enum phaseFunc phaseFuncName,
-
4409  qreal* params, int numParams,
-
4410  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
4411  int conj
-
4412 ) {
-
4413  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4315  // determine if this phase index has an overriden value (i < numOverrides)
+
4316  for (i=0; i<numOverrides; i++)
+
4317  if (phaseInd == overrideInds[i])
+
4318  break;
+
4319 
+
4320  // determine phase from {coeffs}, {exponents} (unless overriden)
+
4321  phase = 0;
+
4322  if (i < numOverrides)
+
4323  phase = overridePhases[i];
+
4324  else
+
4325  for (t=0; t<numTerms; t++)
+
4326  phase += coeffs[t] * pow(phaseInd, exponents[t]);
+
4327 
+
4328  // negate phase to conjugate operator
+
4329  if (conj)
+
4330  phase *= -1;
+
4331 
+
4332  // modify amp to amp * exp(i phase)
+
4333  c = cos(phase);
+
4334  s = sin(phase);
+
4335  re = stateRe[index];
+
4336  im = stateIm[index];
+
4337 
+
4338  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4339  stateRe[index] = re*c - im*s;
+
4340  stateIm[index] = re*s + im*c;
+
4341  }
+
4342  }
+
4343 }
+
4344 
+ +
4346  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
+
4347  qreal* coeffs, qreal* exponents, int* numTermsPerReg,
+
4348  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
4349  int conj)
+
4350 {
+
4351  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4352 
+
4353  // note partitions of qubits, coeffs, exponents and overrideInds are stored flat
+
4354 
+
4355  // thread-shared vaes
+
4356  int chunkId = qureg.chunkId;
+
4357  long long int numAmps = qureg.numAmpsPerChunk;
+
4358  qreal* stateRe = qureg.stateVec.real;
+
4359  qreal* stateIm = qureg.stateVec.imag;
+
4360 
+
4361  // thread-private vars
+
4362  long long int index, globalAmpInd;
+
4363  int r, q, i, t, found, flatInd;
+
4364  qreal phase, c, s, re, im;
+
4365 
+
4366  // each thread has a private static array of length >= numRegs (private var-length is illegal)
+
4367  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
+
4368 
+
4369 # ifdef _OPENMP
+
4370 # pragma omp parallel \
+
4371  default (none) \
+
4372  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, coeffs,exponents,numTermsPerReg, overrideInds,overridePhases,numOverrides, conj) \
+
4373  private (index,globalAmpInd, r,q,i,t,flatInd, found, phaseInds,phase, c,s,re,im)
+
4374 # endif
+
4375  {
+
4376 # ifdef _OPENMP
+
4377 # pragma omp for schedule (static)
+
4378 # endif
+
4379  for (index=0LL; index<numAmps; index++) {
+
4380 
+
4381  // determine global amplitude index
+
4382  globalAmpInd = chunkId * numAmps + index;
+
4383 
+
4384  // determine phase indices
+
4385  flatInd = 0;
+
4386  for (r=0; r<numRegs; r++) {
+
4387  phaseInds[r] = 0LL;
+
4388 
+
4389  if (encoding == UNSIGNED) {
+
4390  for (q=0; q<numQubitsPerReg[r]; q++)
+
4391  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
+
4392  }
+
4393  else if (encoding == TWOS_COMPLEMENT) {
+
4394  for (q=0; q<numQubitsPerReg[r]-1; q++)
+
4395  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
4396  // use final qubit to indicate sign
+
4397  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
4398  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
+
4399  }
+
4400  }
+
4401 
+
4402  // determine if this phase index has an overriden value (i < numOverrides)
+
4403  for (i=0; i<numOverrides; i++) {
+
4404  found = 1;
+
4405  for (r=0; r<numRegs; r++) {
+
4406  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
+
4407  found = 0;
+
4408  break;
+
4409  }
+
4410  }
+
4411  if (found)
+
4412  break;
+
4413  }
4414 
-
4415  // note partitions of qubits, overrideInds are stored flat
-
4416 
-
4417  // thread-shared vaes
-
4418  int chunkId = qureg.chunkId;
-
4419  long long int numAmps = qureg.numAmpsPerChunk;
-
4420  qreal* stateRe = qureg.stateVec.real;
-
4421  qreal* stateIm = qureg.stateVec.imag;
-
4422 
-
4423  // thread-private vars
-
4424  long long int index, globalAmpInd;
-
4425  int r, q, i, found, flatInd;
-
4426  qreal phase, norm, prod, dist, c, s, re, im;
-
4427 
-
4428  // each thread has a private static array of length >= numRegs (private var-length is illegal)
-
4429  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
-
4430 
-
4431 # ifdef _OPENMP
-
4432 # pragma omp parallel \
-
4433  default (none) \
-
4434  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, phaseFuncName,params,numParams, overrideInds,overridePhases,numOverrides, conj) \
-
4435  private (index,globalAmpInd, r,q,i,flatInd, found, phaseInds,phase,norm,prod,dist, c,s,re,im)
-
4436 # endif
-
4437  {
-
4438 # ifdef _OPENMP
-
4439 # pragma omp for schedule (static)
-
4440 # endif
-
4441  for (index=0LL; index<numAmps; index++) {
-
4442 
-
4443  // determine global amplitude index
-
4444  globalAmpInd = chunkId * numAmps + index;
+
4415  // compute the phase (unless overriden)
+
4416  phase = 0;
+
4417  if (i < numOverrides)
+
4418  phase = overridePhases[i];
+
4419  else {
+
4420  flatInd = 0;
+
4421  for (r=0; r<numRegs; r++) {
+
4422  for (t=0; t<numTermsPerReg[r]; t++) {
+
4423  phase += coeffs[flatInd] * pow(phaseInds[r], exponents[flatInd]);
+
4424  flatInd++;
+
4425  }
+
4426  }
+
4427  }
+
4428 
+
4429  // negate phase to conjugate operator
+
4430  if (conj)
+
4431  phase *= -1;
+
4432 
+
4433  // modify amp to amp * exp(i phase)
+
4434  c = cos(phase);
+
4435  s = sin(phase);
+
4436  re = stateRe[index];
+
4437  im = stateIm[index];
+
4438 
+
4439  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4440  stateRe[index] = re*c - im*s;
+
4441  stateIm[index] = re*s + im*c;
+
4442  }
+
4443  }
+
4444 }
4445 
-
4446  // determine phase indices
-
4447  flatInd = 0;
-
4448  for (r=0; r<numRegs; r++) {
-
4449  phaseInds[r] = 0LL;
-
4450 
-
4451  if (encoding == UNSIGNED) {
-
4452  for (q=0; q<numQubitsPerReg[r]; q++)
-
4453  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
-
4454  }
-
4455  else if (encoding == TWOS_COMPLEMENT) {
-
4456  for (q=0; q<numQubitsPerReg[r]-1; q++)
-
4457  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
4458  // use final qubit to indicate sign
-
4459  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
4460  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
-
4461  }
-
4462  }
-
4463 
-
4464  // determine if this phase index has an overriden value (i < numOverrides)
-
4465  for (i=0; i<numOverrides; i++) {
-
4466  found = 1;
-
4467  for (r=0; r<numRegs; r++) {
-
4468  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
-
4469  found = 0;
-
4470  break;
-
4471  }
-
4472  }
-
4473  if (found)
-
4474  break;
-
4475  }
-
4476 
-
4477  // compute the phase (unless overriden)
-
4478  phase = 0;
-
4479  if (i < numOverrides)
-
4480  phase = overridePhases[i];
-
4481  else {
-
4482  // compute norm related phases
-
4483  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
-
4484  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
-
4485  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
4486 
-
4487  norm = 0;
-
4488  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
4489  for (r=0; r<numRegs; r++)
-
4490  norm += (phaseInds[r] - params[2+r])*(phaseInds[r] - params[2+r]);
-
4491  }
-
4492  else
-
4493  for (r=0; r<numRegs; r++)
-
4494  norm += phaseInds[r]*phaseInds[r];
-
4495  norm = sqrt(norm);
-
4496 
-
4497  if (phaseFuncName == NORM)
-
4498  phase = norm;
-
4499  else if (phaseFuncName == INVERSE_NORM)
-
4500  phase = (norm == 0.)? params[0] : 1/norm;
-
4501  else if (phaseFuncName == SCALED_NORM)
-
4502  phase = params[0] * norm;
-
4503  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
-
4504  phase = (norm == 0.)? params[1] : params[0] / norm;
-
4505  }
-
4506  // compute product related phases
-
4507  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
-
4508  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
-
4509 
-
4510  prod = 1;
-
4511  for (r=0; r<numRegs; r++)
-
4512  prod *= phaseInds[r];
-
4513 
-
4514  if (phaseFuncName == PRODUCT)
-
4515  phase = prod;
-
4516  else if (phaseFuncName == INVERSE_PRODUCT)
-
4517  phase = (prod == 0.)? params[0] : 1/prod;
-
4518  else if (phaseFuncName == SCALED_PRODUCT)
-
4519  phase = params[0] * prod;
-
4520  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
-
4521  phase = (prod == 0.)? params[1] : params[0] / prod;
-
4522  }
-
4523  // compute Euclidean distance related phases
-
4524  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
-
4525  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
-
4526  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
4527 
-
4528  dist = 0;
-
4529  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
4530  for (r=0; r<numRegs; r+=2)
-
4531  dist += (phaseInds[r+1] - phaseInds[r] - params[2+r/2])*(phaseInds[r+1] - phaseInds[r] - params[2+r/2]);
-
4532  }
-
4533  else
-
4534  for (r=0; r<numRegs; r+=2)
-
4535  dist += (phaseInds[r+1] - phaseInds[r])*(phaseInds[r+1] - phaseInds[r]);
-
4536  dist = sqrt(dist);
-
4537 
-
4538  if (phaseFuncName == DISTANCE)
-
4539  phase = dist;
-
4540  else if (phaseFuncName == INVERSE_DISTANCE)
-
4541  phase = (dist == 0.)? params[0] : 1/dist;
-
4542  else if (phaseFuncName == SCALED_DISTANCE)
-
4543  phase = params[0] * dist;
-
4544  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
-
4545  phase = (dist == 0.)? params[1] : params[0] / dist;
-
4546  }
-
4547  }
-
4548 
-
4549  // negate phase to conjugate operator
-
4550  if (conj)
-
4551  phase *= -1;
-
4552 
-
4553  // modify amp to amp * exp(i phase)
-
4554  c = cos(phase);
-
4555  s = sin(phase);
-
4556  re = stateRe[index];
-
4557  im = stateIm[index];
-
4558 
-
4559  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4560  stateRe[index] = re*c - im*s;
-
4561  stateIm[index] = re*s + im*c;
-
4562  }
-
4563  }
-
4564 }
-
4565 
+ +
4447  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
+
4448  enum phaseFunc phaseFuncName,
+
4449  qreal* params, int numParams,
+
4450  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
4451  int conj
+
4452 ) {
+
4453  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4454 
+
4455  // note partitions of qubits, overrideInds are stored flat
+
4456 
+
4457  // thread-shared vaes
+
4458  int chunkId = qureg.chunkId;
+
4459  long long int numAmps = qureg.numAmpsPerChunk;
+
4460  qreal* stateRe = qureg.stateVec.real;
+
4461  qreal* stateIm = qureg.stateVec.imag;
+
4462 
+
4463  // thread-private vars
+
4464  long long int index, globalAmpInd;
+
4465  int r, q, i, found, flatInd;
+
4466  qreal phase, norm, prod, dist, c, s, re, im;
+
4467 
+
4468  // each thread has a private static array of length >= numRegs (private var-length is illegal)
+
4469  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
+
4470 
+
4471 # ifdef _OPENMP
+
4472 # pragma omp parallel \
+
4473  default (none) \
+
4474  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, phaseFuncName,params,numParams, overrideInds,overridePhases,numOverrides, conj) \
+
4475  private (index,globalAmpInd, r,q,i,flatInd, found, phaseInds,phase,norm,prod,dist, c,s,re,im)
+
4476 # endif
+
4477  {
+
4478 # ifdef _OPENMP
+
4479 # pragma omp for schedule (static)
+
4480 # endif
+
4481  for (index=0LL; index<numAmps; index++) {
+
4482 
+
4483  // determine global amplitude index
+
4484  globalAmpInd = chunkId * numAmps + index;
+
4485 
+
4486  // determine phase indices
+
4487  flatInd = 0;
+
4488  for (r=0; r<numRegs; r++) {
+
4489  phaseInds[r] = 0LL;
+
4490 
+
4491  if (encoding == UNSIGNED) {
+
4492  for (q=0; q<numQubitsPerReg[r]; q++)
+
4493  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
+
4494  }
+
4495  else if (encoding == TWOS_COMPLEMENT) {
+
4496  for (q=0; q<numQubitsPerReg[r]-1; q++)
+
4497  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
4498  // use final qubit to indicate sign
+
4499  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
4500  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
+
4501  }
+
4502  }
+
4503 
+
4504  // determine if this phase index has an overriden value (i < numOverrides)
+
4505  for (i=0; i<numOverrides; i++) {
+
4506  found = 1;
+
4507  for (r=0; r<numRegs; r++) {
+
4508  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
+
4509  found = 0;
+
4510  break;
+
4511  }
+
4512  }
+
4513  if (found)
+
4514  break;
+
4515  }
+
4516 
+
4517  // compute the phase (unless overriden)
+
4518  phase = 0;
+
4519  if (i < numOverrides)
+
4520  phase = overridePhases[i];
+
4521  else {
+
4522  // compute norm related phases
+
4523  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
+
4524  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
+
4525  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
4526 
+
4527  norm = 0;
+
4528  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
4529  for (r=0; r<numRegs; r++)
+
4530  norm += (phaseInds[r] - params[2+r])*(phaseInds[r] - params[2+r]);
+
4531  }
+
4532  else
+
4533  for (r=0; r<numRegs; r++)
+
4534  norm += phaseInds[r]*phaseInds[r];
+
4535  norm = sqrt(norm);
+
4536 
+
4537  if (phaseFuncName == NORM)
+
4538  phase = norm;
+
4539  else if (phaseFuncName == INVERSE_NORM)
+
4540  phase = (norm == 0.)? params[0] : 1/norm; // smallest non-zero norm is 1
+
4541  else if (phaseFuncName == SCALED_NORM)
+
4542  phase = params[0] * norm;
+
4543  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
+
4544  phase = (norm <= REAL_EPS)? params[1] : params[0] / norm; // unless shifted closer to zero
+
4545  }
+
4546  // compute product related phases
+
4547  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
+
4548  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
+
4549 
+
4550  prod = 1;
+
4551  for (r=0; r<numRegs; r++)
+
4552  prod *= phaseInds[r];
+
4553 
+
4554  if (phaseFuncName == PRODUCT)
+
4555  phase = prod;
+
4556  else if (phaseFuncName == INVERSE_PRODUCT)
+
4557  phase = (prod == 0.)? params[0] : 1/prod; // smallest non-zero product norm is +- 1
+
4558  else if (phaseFuncName == SCALED_PRODUCT)
+
4559  phase = params[0] * prod;
+
4560  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
+
4561  phase = (prod == 0.)? params[1] : params[0] / prod;
+
4562  }
+
4563  // compute Euclidean distance related phases
+
4564  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
+
4565  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
+
4566  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
4567 
+
4568  dist = 0;
+
4569  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
4570  for (r=0; r<numRegs; r+=2)
+
4571  dist += (phaseInds[r] - phaseInds[r+1] - params[2+r/2])*(phaseInds[r] - phaseInds[r+1] - params[2+r/2]);
+
4572  }
+
4573  else
+
4574  for (r=0; r<numRegs; r+=2)
+
4575  dist += (phaseInds[r+1] - phaseInds[r])*(phaseInds[r+1] - phaseInds[r]);
+
4576  dist = sqrt(dist);
+
4577 
+
4578  if (phaseFuncName == DISTANCE)
+
4579  phase = dist;
+
4580  else if (phaseFuncName == INVERSE_DISTANCE)
+
4581  phase = (dist == 0.)? params[0] : 1/dist; // smallest non-zero dist is 1
+
4582  else if (phaseFuncName == SCALED_DISTANCE)
+
4583  phase = params[0] * dist;
+
4584  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
+
4585  phase = (dist <= REAL_EPS)? params[1] : params[0] / dist; // unless shifted closer to 0
+
4586  }
+
4587  }
+
4588 
+
4589  // negate phase to conjugate operator
+
4590  if (conj)
+
4591  phase *= -1;
+
4592 
+
4593  // modify amp to amp * exp(i phase)
+
4594  c = cos(phase);
+
4595  s = sin(phase);
+
4596  re = stateRe[index];
+
4597  im = stateIm[index];
+
4598 
+
4599  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4600  stateRe[index] = re*c - im*s;
+
4601  stateIm[index] = re*s + im*c;
+
4602  }
+
4603  }
+
4604 }
@ INVERSE_PRODUCT
Definition: QuEST.h:233
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1897
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3319
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:39
-
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_cpu.c:1366
+
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1908
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3358
+
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:45
+
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_cpu.c:1377
qreal real[4][4]
Definition: QuEST.h:177
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
@ PAULI_Z
Definition: QuEST.h:96
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3187
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
+
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3226
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
@ DISTANCE
Definition: QuEST.h:234
-
int rank
Definition: QuEST.h:363
-
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4228
+
int rank
Definition: QuEST.h:364
+
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4268
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:304
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:4188
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1115
+
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:4228
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
+
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1126
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1646
+
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1657
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3474
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
+
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3513
+
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:230
+
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:638
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
-
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3268
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2503
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2437
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1561
+
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3307
+
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2542
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2476
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1572
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:306
@ NORM
Definition: QuEST.h:232
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
+
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1248
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
-
Information about the environment the program is running in.
Definition: QuEST.h:361
+
Information about the environment the program is running in.
Definition: QuEST.h:362
@ UNSIGNED
Definition: QuEST.h:269
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1525
+
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1536
@ INVERSE_DISTANCE
Definition: QuEST.h:234
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2612
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
+
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2651
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:85
#define qreal
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1357
-
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
+
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1368
+
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3227
+
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3266
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc phaseFuncName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4406
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3847
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc phaseFuncName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
+
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3887
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
qreal imag[2][2]
Definition: QuEST.h:140
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3647
+
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3687
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1483
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1493
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
+
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1494
+
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1504
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1279
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2943
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
+
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1290
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
+
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:54
+
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:901
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:36
+
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:42
@ SCALED_PRODUCT
Definition: QuEST.h:233
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
-
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:754
-
int numRanks
Definition: QuEST.h:364
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2056
+
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:760
+
int numRanks
Definition: QuEST.h:365
+
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2095
qreal imag[4][4]
Definition: QuEST.h:178
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:744
+
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:750
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2906
+
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2945
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
+
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:306
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
qreal ** real
Definition: QuEST.h:189
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1362
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1373
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
@ INVERSE_NORM
Definition: QuEST.h:232
Represents a system of qubits.
Definition: QuEST.h:322
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
qreal ** imag
Definition: QuEST.h:190
-
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2795
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2112
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2375
+
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2834
+
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2151
+
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2414
@ PRODUCT
Definition: QuEST.h:233
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1730
+
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1741
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3678
+
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3718
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
-
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4305
+
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4345
qreal real[2][2]
Definition: QuEST.h:139
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3809
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3849
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
int numQubits
Definition: QuEST.h:188
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
static int isOddParity(const long long int number, const int qb1, const int qb2)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1317
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3277
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
+
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1328
+
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:494
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3316
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2703
+
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2742
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3925
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1680
+
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3965
+
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1691
qreal imag
Definition: QuEST.h:106
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
+
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:547
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3100
+
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3139
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Definition: QuEST_cpu.c:1428
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3965
-
void densmatr_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1154
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1600
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2997
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4007
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
+
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Definition: QuEST_cpu.c:1439
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:4005
+
void densmatr_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1165
+
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1611
+
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:3036
+
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4047
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3146
+
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3185
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:734
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1335
+
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:740
+
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1346
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
diff --git a/docs/QuEST__cpu__distributed_8c.html b/docs/QuEST__cpu__distributed_8c.html index 9ba7902e3..55ab921d4 100644 --- a/docs/QuEST__cpu__distributed_8c.html +++ b/docs/QuEST__cpu__distributed_8c.html @@ -27,7 +27,7 @@ @@ -168,9 +168,9 @@ void reportQuESTEnv (QuESTEnv env)  Report information about the QuEST environment. More...
  -void seedQuESTDefault () - Seed the Mersenne Twister used for random number generation in the QuEST environment with an example default seed. More...
-  +void seedQuEST (QuESTEnv *env, unsigned long int *seedArray, int numSeeds) + Seeds the random number generator with a custom array of key(s), overriding the default keys. More...
Complex statevec_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)   Complex statevec_calcInnerProduct (Qureg bra, Qureg ket) @@ -306,15 +306,15 @@

Returns
1: chunk is in upper half of block, 0: chunk is in lower half of block fix – is this the same as isChunkToSkip?
-

Definition at line 237 of file QuEST_cpu_distributed.c.

-
238 {
-
239  long long int sizeHalfBlock = 1LL << (targetQubit);
-
240  long long int sizeBlock = sizeHalfBlock*2;
-
241  long long int posInBlock = (chunkId*chunkSize) % sizeBlock;
-
242  return posInBlock<sizeHalfBlock;
-
243 }
+

Definition at line 241 of file QuEST_cpu_distributed.c.

+
242 {
+
243  long long int sizeHalfBlock = 1LL << (targetQubit);
+
244  long long int sizeBlock = sizeHalfBlock*2;
+
245  long long int posInBlock = (chunkId*chunkSize) % sizeBlock;
+
246  return posInBlock<sizeHalfBlock;
+
247 }
-

Referenced by getChunkOuterBlockPairId(), getChunkPairId(), getRotAngle(), getRotAngleFromUnitaryMatrix(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), and statevec_unitary().

+

Referenced by getChunkOuterBlockPairId(), getChunkPairId(), getRotAngle(), getRotAngleFromUnitaryMatrix(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), and statevec_unitary().

@@ -366,15 +366,15 @@

Definition at line 246 of file QuEST_cpu_distributed.c.

-
247 {
-
248  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
249  long long int sizeOuterBlock = sizeOuterHalfBlock*2;
-
250  long long int posInBlock = (chunkId*chunkSize) % sizeOuterBlock;
-
251  return posInBlock<sizeOuterHalfBlock;
-
252 }
+

Definition at line 250 of file QuEST_cpu_distributed.c.

+
251 {
+
252  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
+
253  long long int sizeOuterBlock = sizeOuterHalfBlock*2;
+
254  long long int posInBlock = (chunkId*chunkSize) % sizeOuterBlock;
+
255  return posInBlock<sizeOuterHalfBlock;
+
256 }
-

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

@@ -404,77 +404,77 @@

-

Definition at line 553 of file QuEST_cpu_distributed.c.

-
553  {
-
554  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
555  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
556  long long int thisInnerBlock, // current block
-
557  thisOuterColumn, // current column in density matrix
-
558  thisIndex, // current index in (density matrix representation) state vector
-
559  thisIndexInOuterColumn,
-
560  thisIndexInInnerBlock;
-
561 
-
562  int outerBit;
-
563 
-
564  long long int thisTask;
-
565  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
566 
-
567  // set dimensions
-
568  sizeInnerHalfBlock = 1LL << targetQubit;
-
569  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
570  sizeOuterHalfColumn = 1LL << qureg.numQubitsRepresented;
-
571  sizeOuterColumn = 2LL * sizeOuterHalfColumn;
-
572 
-
573 # ifdef _OPENMP
-
574 # pragma omp parallel \
-
575  default (none) \
-
576  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
577  qureg,numTasks,targetQubit) \
-
578  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
579  thisIndexInInnerBlock,outerBit)
-
580 # endif
-
581  {
-
582 # ifdef _OPENMP
-
583 # pragma omp for schedule (static)
+

Definition at line 557 of file QuEST_cpu_distributed.c.

+
557  {
+
558  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
559  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
560  long long int thisInnerBlock, // current block
+
561  thisOuterColumn, // current column in density matrix
+
562  thisIndex, // current index in (density matrix representation) state vector
+
563  thisIndexInOuterColumn,
+
564  thisIndexInInnerBlock;
+
565 
+
566  int outerBit;
+
567 
+
568  long long int thisTask;
+
569  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
570 
+
571  // set dimensions
+
572  sizeInnerHalfBlock = 1LL << targetQubit;
+
573  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
574  sizeOuterHalfColumn = 1LL << qureg.numQubitsRepresented;
+
575  sizeOuterColumn = 2LL * sizeOuterHalfColumn;
+
576 
+
577 # ifdef _OPENMP
+
578 # pragma omp parallel \
+
579  default (none) \
+
580  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
581  qureg,numTasks,targetQubit) \
+
582  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
583  thisIndexInInnerBlock,outerBit)
584 # endif
-
585  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
586  // treat this as iterating over all columns, then iterating over half the values
-
587  // within one column.
-
588  // If this function has been called, this process' chunk contains half an
-
589  // outer block or less
-
590  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
591  // we want to process all columns in the density matrix,
-
592  // updating the values for half of each column (one half of each inner block)
-
593  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
594  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
595  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
596  // get index in state vector corresponding to upper inner block
-
597  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
598  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
599  + thisIndexInInnerBlock;
-
600  // check if we are in the upper or lower half of an outer block
-
601  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
602  // if we are in the lower half of an outer block, shift to be in the lower half
-
603  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
604  thisIndex += outerBit*(sizeInnerHalfBlock);
-
605 
-
606  // NOTE: at this point thisIndex should be the index of the element we want to
-
607  // dephase in the chunk of the state vector on this process, in the
-
608  // density matrix representation.
-
609  // thisTask is the index of the pair element in pairStateVec
-
610  // we will populate the second half of pairStateVec with this process'
-
611  // data to send
-
612 
-
613  qureg.pairStateVec.real[thisTask+numTasks] = qureg.stateVec.real[thisIndex];
-
614  qureg.pairStateVec.imag[thisTask+numTasks] = qureg.stateVec.imag[thisIndex];
-
615 
-
616  }
-
617  }
-
618 }
+
585  {
+
586 # ifdef _OPENMP
+
587 # pragma omp for schedule (static)
+
588 # endif
+
589  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
590  // treat this as iterating over all columns, then iterating over half the values
+
591  // within one column.
+
592  // If this function has been called, this process' chunk contains half an
+
593  // outer block or less
+
594  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
595  // we want to process all columns in the density matrix,
+
596  // updating the values for half of each column (one half of each inner block)
+
597  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
598  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
599  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
600  // get index in state vector corresponding to upper inner block
+
601  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
602  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
603  + thisIndexInInnerBlock;
+
604  // check if we are in the upper or lower half of an outer block
+
605  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
606  // if we are in the lower half of an outer block, shift to be in the lower half
+
607  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
608  thisIndex += outerBit*(sizeInnerHalfBlock);
+
609 
+
610  // NOTE: at this point thisIndex should be the index of the element we want to
+
611  // dephase in the chunk of the state vector on this process, in the
+
612  // density matrix representation.
+
613  // thisTask is the index of the pair element in pairStateVec
+
614  // we will populate the second half of pairStateVec with this process'
+
615  // data to send
+
616 
+
617  qureg.pairStateVec.real[thisTask+numTasks] = qureg.stateVec.real[thisIndex];
+
618  qureg.pairStateVec.imag[thisTask+numTasks] = qureg.stateVec.imag[thisIndex];
+
619 
+
620  }
+
621  }
+
622 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixDamping(), and densmatr_mixDepolarising().

+

Referenced by densmatr_mixDamping(), and densmatr_mixDepolarising().

@@ -510,96 +510,96 @@

-

Definition at line 620 of file QuEST_cpu_distributed.c.

-
621  {
-
622 
-
623  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
624  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
625  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
626  long long int
-
627  thisInnerBlockQ2,
-
628  thisOuterColumn, // current column in density matrix
-
629  thisIndex, // current index in (density matrix representation) state vector
-
630  thisIndexInOuterColumn,
-
631  thisIndexInInnerBlockQ1,
-
632  thisIndexInInnerBlockQ2,
-
633  thisInnerBlockQ1InInnerBlockQ2;
-
634  int outerBitQ1, outerBitQ2;
-
635 
-
636  long long int thisTask;
-
637  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
638 
-
639  // set dimensions
-
640  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
641  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
642  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
643  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
644  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
645  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
646  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
647 
-
648 # ifdef _OPENMP
-
649 # pragma omp parallel \
-
650  default (none) \
-
651  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerQuarterBlockQ2,sizeInnerHalfBlockQ2,sizeInnerBlockQ2, \
-
652  sizeOuterColumn,sizeOuterQuarterColumn,qureg,numTasks,targetQubit,qubit2) \
-
653  private (thisTask,thisInnerBlockQ2,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
654  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2,outerBitQ1,outerBitQ2)
-
655 # endif
-
656  {
-
657 # ifdef _OPENMP
-
658 # pragma omp for schedule (static)
+

Definition at line 624 of file QuEST_cpu_distributed.c.

+
625  {
+
626 
+
627  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
628  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
629  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
630  long long int
+
631  thisInnerBlockQ2,
+
632  thisOuterColumn, // current column in density matrix
+
633  thisIndex, // current index in (density matrix representation) state vector
+
634  thisIndexInOuterColumn,
+
635  thisIndexInInnerBlockQ1,
+
636  thisIndexInInnerBlockQ2,
+
637  thisInnerBlockQ1InInnerBlockQ2;
+
638  int outerBitQ1, outerBitQ2;
+
639 
+
640  long long int thisTask;
+
641  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
642 
+
643  // set dimensions
+
644  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
645  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
646  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
647  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
648  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
649  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
650  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
651 
+
652 # ifdef _OPENMP
+
653 # pragma omp parallel \
+
654  default (none) \
+
655  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerQuarterBlockQ2,sizeInnerHalfBlockQ2,sizeInnerBlockQ2, \
+
656  sizeOuterColumn,sizeOuterQuarterColumn,qureg,numTasks,targetQubit,qubit2) \
+
657  private (thisTask,thisInnerBlockQ2,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
658  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2,outerBitQ1,outerBitQ2)
659 # endif
-
660  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
661  // treat this as iterating over all columns, then iterating over half the values
-
662  // within one column.
-
663  // If this function has been called, this process' chunk contains half an
-
664  // outer block or less
-
665  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
666  // we want to process all columns in the density matrix,
-
667  // updating the values for half of each column (one half of each inner block)
-
668  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
669  // thisTask % sizeOuterQuarterColumn
-
670  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
671  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
672  // thisTask % sizeInnerQuarterBlockQ2;
-
673  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
674  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
675  // thisTask % sizeInnerHalfBlockQ1;
-
676  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
677 
-
678  // get index in state vector corresponding to upper inner block
-
679  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
680  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
660  {
+
661 # ifdef _OPENMP
+
662 # pragma omp for schedule (static)
+
663 # endif
+
664  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
665  // treat this as iterating over all columns, then iterating over half the values
+
666  // within one column.
+
667  // If this function has been called, this process' chunk contains half an
+
668  // outer block or less
+
669  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
670  // we want to process all columns in the density matrix,
+
671  // updating the values for half of each column (one half of each inner block)
+
672  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
673  // thisTask % sizeOuterQuarterColumn
+
674  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
675  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
676  // thisTask % sizeInnerQuarterBlockQ2;
+
677  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
678  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
679  // thisTask % sizeInnerHalfBlockQ1;
+
680  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
681 
-
682  // check if we are in the upper or lower half of an outer block for Q1
-
683  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
684  // if we are in the lower half of an outer block, shift to be in the lower half
-
685  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
686  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
687 
-
688  // check if we are in the upper or lower half of an outer block for Q2
-
689  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
690  // if we are in the lower half of an outer block, shift to be in the lower half
-
691  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
692  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
693 
-
694  // NOTE: at this point thisIndex should be the index of the element we want to
-
695  // dephase in the chunk of the state vector on this process, in the
-
696  // density matrix representation.
-
697  // thisTask is the index of the pair element in pairStateVec
-
698 
-
699  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
700  // + pair[thisTask])/2
-
701  qureg.pairStateVec.real[thisTask+numTasks*2] = qureg.stateVec.real[thisIndex];
-
702  qureg.pairStateVec.imag[thisTask+numTasks*2] = qureg.stateVec.imag[thisIndex];
-
703  }
-
704  }
-
705 }
+
682  // get index in state vector corresponding to upper inner block
+
683  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
684  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
685 
+
686  // check if we are in the upper or lower half of an outer block for Q1
+
687  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
688  // if we are in the lower half of an outer block, shift to be in the lower half
+
689  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
690  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+
691 
+
692  // check if we are in the upper or lower half of an outer block for Q2
+
693  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
694  // if we are in the lower half of an outer block, shift to be in the lower half
+
695  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
696  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
697 
+
698  // NOTE: at this point thisIndex should be the index of the element we want to
+
699  // dephase in the chunk of the state vector on this process, in the
+
700  // density matrix representation.
+
701  // thisTask is the index of the pair element in pairStateVec
+
702 
+
703  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
704  // + pair[thisTask])/2
+
705  qureg.pairStateVec.real[thisTask+numTasks*2] = qureg.stateVec.real[thisIndex];
+
706  qureg.pairStateVec.imag[thisTask+numTasks*2] = qureg.stateVec.imag[thisIndex];
+
707  }
+
708  }
+
709 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -629,45 +629,45 @@

-

Definition at line 1548 of file QuEST_cpu_distributed.c.

-
1548  {
-
1549 
-
1550  /* since, for every elem in 2^N op, there is a column in 2^N x 2^N qureg,
-
1551  * we know immediately (by each node containing at least 1 element of op)
-
1552  * that every node contains at least 1 column. Hence, we know that pairStateVec
-
1553  * of qureg can fit the entirety of op.
-
1554  */
-
1555 
-
1556  // load up our local contribution
-
1557  long long int localOffset = qureg.chunkId * op.numElemsPerChunk;
-
1558  memcpy(&qureg.pairStateVec.real[localOffset], op.real, op.numElemsPerChunk * sizeof(qreal));
-
1559  memcpy(&qureg.pairStateVec.imag[localOffset], op.imag, op.numElemsPerChunk * sizeof(qreal));
-
1560 
-
1561  // work out how many messages are needed to send op chunks (2GB limit)
-
1562  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
1563  if (op.numElemsPerChunk < maxMsgSize)
-
1564  maxMsgSize = op.numElemsPerChunk;
-
1565  int numMsgs = op.numElemsPerChunk / maxMsgSize; // since MPI_MAX... = 2^n, division is exact
-
1566 
-
1567  // each node has a turn at broadcasting its contribution of op
-
1568  for (int broadcaster=0; broadcaster < qureg.numChunks; broadcaster++) {
-
1569  long long int broadOffset = broadcaster * op.numElemsPerChunk;
-
1570 
-
1571  // (while keeping each message smaller than MPI max)
-
1572  for (int i=0; i<numMsgs; i++) {
-
1573  MPI_Bcast(
-
1574  &qureg.pairStateVec.real[broadOffset + i*maxMsgSize],
-
1575  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1576  MPI_Bcast(
-
1577  &qureg.pairStateVec.imag[broadOffset + i*maxMsgSize],
-
1578  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1579  }
-
1580  }
-
1581 }
+

Definition at line 1559 of file QuEST_cpu_distributed.c.

+
1559  {
+
1560 
+
1561  /* since, for every elem in 2^N op, there is a column in 2^N x 2^N qureg,
+
1562  * we know immediately (by each node containing at least 1 element of op)
+
1563  * that every node contains at least 1 column. Hence, we know that pairStateVec
+
1564  * of qureg can fit the entirety of op.
+
1565  */
+
1566 
+
1567  // load up our local contribution
+
1568  long long int localOffset = qureg.chunkId * op.numElemsPerChunk;
+
1569  memcpy(&qureg.pairStateVec.real[localOffset], op.real, op.numElemsPerChunk * sizeof(qreal));
+
1570  memcpy(&qureg.pairStateVec.imag[localOffset], op.imag, op.numElemsPerChunk * sizeof(qreal));
+
1571 
+
1572  // work out how many messages are needed to send op chunks (2GB limit)
+
1573  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
+
1574  if (op.numElemsPerChunk < maxMsgSize)
+
1575  maxMsgSize = op.numElemsPerChunk;
+
1576  int numMsgs = op.numElemsPerChunk / maxMsgSize; // since MPI_MAX... = 2^n, division is exact
+
1577 
+
1578  // each node has a turn at broadcasting its contribution of op
+
1579  for (int broadcaster=0; broadcaster < qureg.numChunks; broadcaster++) {
+
1580  long long int broadOffset = broadcaster * op.numElemsPerChunk;
+
1581 
+
1582  // (while keeping each message smaller than MPI max)
+
1583  for (int i=0; i<numMsgs; i++) {
+
1584  MPI_Bcast(
+
1585  &qureg.pairStateVec.real[broadOffset + i*maxMsgSize],
+
1586  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
1587  MPI_Bcast(
+
1588  &qureg.pairStateVec.imag[broadOffset + i*maxMsgSize],
+
1589  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
1590  }
+
1591  }
+
1592 }

References Qureg::chunkId, DiagonalOp::imag, Qureg::numChunks, DiagonalOp::numElemsPerChunk, Qureg::pairStateVec, qreal, and DiagonalOp::real.

-

Referenced by densmatr_applyDiagonalOp().

+

Referenced by densmatr_applyDiagonalOp().

@@ -700,54 +700,54 @@

Definition at line 381 of file QuEST_cpu_distributed.c.

-
381  {
-
382 
-
383  // Remember that for every amplitude that `vec` stores on the node,
-
384  // `matr` stores an entire column. Ergo there are always an integer
-
385  // number (in fact, a power of 2) number of `matr`s columns on each node.
-
386  // Since the total size of `vec` (between all nodes) is one column
-
387  // and each node stores (possibly) multiple columns (vec.numAmpsPerChunk as many),
-
388  // `vec` can be fit entirely inside a single node's matr.pairStateVec (with excess!)
-
389 
-
390  // copy this node's vec segment into this node's matr pairState (in the right spot)
-
391  long long int numLocalAmps = vec.numAmpsPerChunk;
-
392  long long int myOffset = vec.chunkId * numLocalAmps;
-
393  memcpy(&matr.pairStateVec.real[myOffset], vec.stateVec.real, numLocalAmps * sizeof(qreal));
-
394  memcpy(&matr.pairStateVec.imag[myOffset], vec.stateVec.imag, numLocalAmps * sizeof(qreal));
-
395 
-
396  // we now want to share this node's vec segment with other node, so that
-
397  // vec is cloned in every node's matr.pairStateVec
-
398 
-
399  // work out how many messages needed to send vec chunks (2GB limit)
-
400  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
401  if (numLocalAmps < maxMsgSize)
-
402  maxMsgSize = numLocalAmps;
-
403  // safely assume MPI_MAX... = 2^n, so division always exact:
-
404  int numMsgs = numLocalAmps / maxMsgSize;
-
405 
-
406  // every node gets a turn at being the broadcaster
-
407  for (int broadcaster=0; broadcaster < vec.numChunks; broadcaster++) {
-
408 
-
409  long long int otherOffset = broadcaster * numLocalAmps;
-
410 
-
411  // every node sends a slice of qureg's pairState to every other
-
412  for (int i=0; i< numMsgs; i++) {
-
413 
-
414  // by sending that slice in further slices (due to bandwidth limit)
-
415  MPI_Bcast(
-
416  &matr.pairStateVec.real[otherOffset + i*maxMsgSize],
-
417  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
418  MPI_Bcast(
-
419  &matr.pairStateVec.imag[otherOffset + i*maxMsgSize],
-
420  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
421  }
-
422  }
-
423 }
+

Definition at line 385 of file QuEST_cpu_distributed.c.

+
385  {
+
386 
+
387  // Remember that for every amplitude that `vec` stores on the node,
+
388  // `matr` stores an entire column. Ergo there are always an integer
+
389  // number (in fact, a power of 2) number of `matr`s columns on each node.
+
390  // Since the total size of `vec` (between all nodes) is one column
+
391  // and each node stores (possibly) multiple columns (vec.numAmpsPerChunk as many),
+
392  // `vec` can be fit entirely inside a single node's matr.pairStateVec (with excess!)
+
393 
+
394  // copy this node's vec segment into this node's matr pairState (in the right spot)
+
395  long long int numLocalAmps = vec.numAmpsPerChunk;
+
396  long long int myOffset = vec.chunkId * numLocalAmps;
+
397  memcpy(&matr.pairStateVec.real[myOffset], vec.stateVec.real, numLocalAmps * sizeof(qreal));
+
398  memcpy(&matr.pairStateVec.imag[myOffset], vec.stateVec.imag, numLocalAmps * sizeof(qreal));
+
399 
+
400  // we now want to share this node's vec segment with other node, so that
+
401  // vec is cloned in every node's matr.pairStateVec
+
402 
+
403  // work out how many messages needed to send vec chunks (2GB limit)
+
404  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
+
405  if (numLocalAmps < maxMsgSize)
+
406  maxMsgSize = numLocalAmps;
+
407  // safely assume MPI_MAX... = 2^n, so division always exact:
+
408  int numMsgs = numLocalAmps / maxMsgSize;
+
409 
+
410  // every node gets a turn at being the broadcaster
+
411  for (int broadcaster=0; broadcaster < vec.numChunks; broadcaster++) {
+
412 
+
413  long long int otherOffset = broadcaster * numLocalAmps;
+
414 
+
415  // every node sends a slice of qureg's pairState to every other
+
416  for (int i=0; i< numMsgs; i++) {
+
417 
+
418  // by sending that slice in further slices (due to bandwidth limit)
+
419  MPI_Bcast(
+
420  &matr.pairStateVec.real[otherOffset + i*maxMsgSize],
+
421  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
422  MPI_Bcast(
+
423  &matr.pairStateVec.imag[otherOffset + i*maxMsgSize],
+
424  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
425  }
+
426  }
+
427 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcFidelity(), and densmatr_initPureState().

+

Referenced by densmatr_calcFidelity(), and densmatr_initPureState().

@@ -791,14 +791,14 @@

-

Definition at line 373 of file QuEST_cpu_distributed.c.

-
373  {
-
374  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
375  if (chunkSize > sizeOuterHalfBlock) return 1;
-
376  else return 0;
-
377 }
+

Definition at line 377 of file QuEST_cpu_distributed.c.

+
377  {
+
378  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
+
379  if (chunkSize > sizeOuterHalfBlock) return 1;
+
380  else return 0;
+
381 }
-

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

@@ -828,14 +828,14 @@

-

Definition at line 1583 of file QuEST_cpu_distributed.c.

-
1583  {
-
1584 
-
1585  copyDiagOpIntoMatrixPairState(qureg, op);
-
1586  densmatr_applyDiagonalOpLocal(qureg, op);
-
1587 }
+

Definition at line 1594 of file QuEST_cpu_distributed.c.

+
1594  {
+
1595 
+
1596  copyDiagOpIntoMatrixPairState(qureg, op);
+
1597  densmatr_applyDiagonalOpLocal(qureg, op);
+
1598 }
-

References copyDiagOpIntoMatrixPairState(), and densmatr_applyDiagonalOpLocal().

+

References copyDiagOpIntoMatrixPairState(), and densmatr_applyDiagonalOpLocal().

@@ -865,27 +865,27 @@

-

Definition at line 1607 of file QuEST_cpu_distributed.c.

-
1607  {
-
1608 
-
1609  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
1610  if (qureg.numChunks == 1)
-
1611  return localVal;
-
1612 
-
1613  qreal localRe = localVal.real;
-
1614  qreal localIm = localVal.imag;
-
1615  qreal globalRe, globalIm;
-
1616 
-
1617  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1618  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+

Definition at line 1618 of file QuEST_cpu_distributed.c.

+
1618  {
1619 
-
1620  Complex globalVal;
-
1621  globalVal.real = globalRe;
-
1622  globalVal.imag = globalIm;
-
1623  return globalVal;
-
1624 }
+
1620  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
+
1621  if (qureg.numChunks == 1)
+
1622  return localVal;
+
1623 
+
1624  qreal localRe = localVal.real;
+
1625  qreal localIm = localVal.imag;
+
1626  qreal globalRe, globalIm;
+
1627 
+
1628  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1629  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1630 
+
1631  Complex globalVal;
+
1632  globalVal.real = globalRe;
+
1633  globalVal.imag = globalIm;
+
1634  return globalVal;
+
1635 }
-

References densmatr_calcExpecDiagonalOpLocal(), Complex::imag, Qureg::numChunks, qreal, and Complex::real.

+

References densmatr_calcExpecDiagonalOpLocal(), Complex::imag, Qureg::numChunks, qreal, and Complex::real.

@@ -915,23 +915,23 @@

-

Definition at line 425 of file QuEST_cpu_distributed.c.

-
425  {
-
426 
-
427  // set qureg's pairState is to be the full pureState (on every node)
-
428  copyVecIntoMatrixPairState(qureg, pureState);
-
429 
-
430  // collect calcFidelityLocal by every machine
-
431  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
-
432 
-
433  // sum each localSum
-
434  qreal globalSum;
-
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+

Definition at line 429 of file QuEST_cpu_distributed.c.

+
429  {
+
430 
+
431  // set qureg's pairState is to be the full pureState (on every node)
+
432  copyVecIntoMatrixPairState(qureg, pureState);
+
433 
+
434  // collect calcFidelityLocal by every machine
+
435  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
436 
-
437  return globalSum;
-
438 }
+
437  // sum each localSum
+
438  qreal globalSum;
+
439  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
440 
+
441  return globalSum;
+
442 }
-

References copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), and qreal.

+

References copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), and qreal.

@@ -961,19 +961,19 @@

-

Definition at line 440 of file QuEST_cpu_distributed.c.

-
440  {
-
441 
- -
443 
-
444  qreal globalSum;
-
445  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
446 
-
447  qreal dist = sqrt(globalSum);
-
448  return dist;
-
449 }
+

Definition at line 444 of file QuEST_cpu_distributed.c.

+
444  {
+
445 
+ +
447 
+
448  qreal globalSum;
+
449  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
450 
+
451  qreal dist = sqrt(globalSum);
+
452  return dist;
+
453 }
-

References densmatr_calcHilbertSchmidtDistanceSquaredLocal(), and qreal.

+

References densmatr_calcHilbertSchmidtDistanceSquaredLocal(), and qreal.

@@ -1003,19 +1003,19 @@

-

Definition at line 451 of file QuEST_cpu_distributed.c.

-
451  {
-
452 
-
453  qreal localSum = densmatr_calcInnerProductLocal(a, b);
-
454 
-
455  qreal globalSum;
-
456  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
457 
-
458  qreal dist = globalSum;
-
459  return dist;
-
460 }
+

Definition at line 455 of file QuEST_cpu_distributed.c.

+
455  {
+
456 
+
457  qreal localSum = densmatr_calcInnerProductLocal(a, b);
+
458 
+
459  qreal globalSum;
+
460  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
461 
+
462  qreal dist = globalSum;
+
463  return dist;
+
464 }
-

References densmatr_calcInnerProductLocal(), and qreal.

+

References densmatr_calcInnerProductLocal(), and qreal.

@@ -1057,17 +1057,17 @@

-

Definition at line 1345 of file QuEST_cpu_distributed.c.

-
1345  {
-
1346 
-
1347  // each node populates retProbs with contributions from the subset of amps in each
-
1348  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
1349 
-
1350  // then, retProbs are summed element-wise
-
1351  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1352 }
+

Definition at line 1349 of file QuEST_cpu_distributed.c.

+
1349  {
+
1350 
+
1351  // each node populates retProbs with contributions from the subset of amps in each
+
1352  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
1353 
+
1354  // then, retProbs are summed element-wise
+
1355  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1356 }
-

References densmatr_calcProbOfAllOutcomesLocal().

+

References densmatr_calcProbOfAllOutcomesLocal().

@@ -1103,20 +1103,20 @@

-

Definition at line 1324 of file QuEST_cpu_distributed.c.

-
1324  {
-
1325 
-
1326  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1327 
-
1328  qreal outcomeProb;
-
1329  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1330  if (outcome == 1)
-
1331  outcomeProb = 1.0 - outcomeProb;
-
1332 
-
1333  return outcomeProb;
-
1334 }
+

Definition at line 1328 of file QuEST_cpu_distributed.c.

+
1328  {
+
1329 
+
1330  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
+
1331 
+
1332  qreal outcomeProb;
+
1333  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1334  if (outcome == 1)
+
1335  outcomeProb = 1.0 - outcomeProb;
+
1336 
+
1337  return outcomeProb;
+
1338 }
-

References densmatr_findProbabilityOfZeroLocal(), and qreal.

+

References densmatr_findProbabilityOfZeroLocal(), and qreal.

@@ -1136,18 +1136,18 @@

-

Definition at line 1354 of file QuEST_cpu_distributed.c.

-
1354  {
-
1355 
-
1356  qreal localPurity = densmatr_calcPurityLocal(qureg);
-
1357 
-
1358  qreal globalPurity;
-
1359  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1360 
-
1361  return globalPurity;
-
1362 }
+

Definition at line 1358 of file QuEST_cpu_distributed.c.

+
1358  {
+
1359 
+
1360  qreal localPurity = densmatr_calcPurityLocal(qureg);
+
1361 
+
1362  qreal globalPurity;
+
1363  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1364 
+
1365  return globalPurity;
+
1366 }
-

References densmatr_calcPurityLocal(), and qreal.

+

References densmatr_calcPurityLocal(), and qreal.

@@ -1233,35 +1233,35 @@

-

Definition at line 462 of file QuEST_cpu_distributed.c.

-
462  {
-
463 
-
464  if (targetQureg.numChunks==1){
-
465  // local version
-
466  // save pointers to qureg's pair state
-
467  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
-
468  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
-
469 
-
470  // populate qureg pair state with pure state (by repointing)
-
471  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
-
472  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
+

Definition at line 466 of file QuEST_cpu_distributed.c.

+
466  {
+
467 
+
468  if (targetQureg.numChunks==1){
+
469  // local version
+
470  // save pointers to qureg's pair state
+
471  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
+
472  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
473 
-
474  // populate density matrix via it's pairState
-
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
476 
-
477  // restore pointers
-
478  targetQureg.pairStateVec.real = quregPairRePtr;
-
479  targetQureg.pairStateVec.imag = quregPairImPtr;
-
480  } else {
-
481  // set qureg's pairState is to be the full pure state (on every node)
-
482  copyVecIntoMatrixPairState(targetQureg, copyQureg);
-
483 
-
484  // update every density matrix chunk using pairState
-
485  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
486  }
-
487 }
+
474  // populate qureg pair state with pure state (by repointing)
+
475  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
+
476  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
+
477 
+
478  // populate density matrix via it's pairState
+
479  densmatr_initPureStateLocal(targetQureg, copyQureg);
+
480 
+
481  // restore pointers
+
482  targetQureg.pairStateVec.real = quregPairRePtr;
+
483  targetQureg.pairStateVec.imag = quregPairImPtr;
+
484  } else {
+
485  // set qureg's pairState is to be the full pure state (on every node)
+
486  copyVecIntoMatrixPairState(targetQureg, copyQureg);
+
487 
+
488  // update every density matrix chunk using pairState
+
489  densmatr_initPureStateLocal(targetQureg, copyQureg);
+
490  }
+
491 }
-

References copyVecIntoMatrixPairState(), densmatr_initPureStateLocal(), Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

+

References copyVecIntoMatrixPairState(), densmatr_initPureStateLocal(), Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

@@ -1297,35 +1297,35 @@

-

Definition at line 735 of file QuEST_cpu_distributed.c.

-
735  {
-
736  if (damping == 0)
-
737  return;
-
738 
-
739  int rankIsUpper; // rank is in the upper half of an outer block
-
740  int pairRank; // rank of corresponding chunk
-
741 
-
742  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
743  qureg.numQubitsRepresented, targetQubit);
-
744 
-
745  if (useLocalDataOnly){
-
746  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
747  } else {
-
748  // pack data to send to my pair process into the first half of pairStateVec
-
749  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
750 
-
751  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
752  qureg.numQubitsRepresented);
-
753  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
754  targetQubit, qureg.numQubitsRepresented);
-
755 
-
756  exchangePairStateVectorHalves(qureg, pairRank);
-
757  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
-
758  }
+

Definition at line 739 of file QuEST_cpu_distributed.c.

+
739  {
+
740  if (damping == 0)
+
741  return;
+
742 
+
743  int rankIsUpper; // rank is in the upper half of an outer block
+
744  int pairRank; // rank of corresponding chunk
+
745 
+
746  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
747  qureg.numQubitsRepresented, targetQubit);
+
748 
+
749  if (useLocalDataOnly){
+
750  densmatr_mixDampingLocal(qureg, targetQubit, damping);
+
751  } else {
+
752  // pack data to send to my pair process into the first half of pairStateVec
+
753  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
+
754 
+
755  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
+
756  qureg.numQubitsRepresented);
+
757  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
+
758  targetQubit, qureg.numQubitsRepresented);
759 
-
760 }
+
760  exchangePairStateVectorHalves(qureg, pairRank);
+
761  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
+
762  }
+
763 
+
764 }
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, and Qureg::numQubitsRepresented.

+

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, and Qureg::numQubitsRepresented.

@@ -1361,35 +1361,35 @@

-

Definition at line 708 of file QuEST_cpu_distributed.c.

-
708  {
-
709  if (depolLevel == 0)
-
710  return;
-
711 
-
712  int rankIsUpper; // rank is in the upper half of an outer block
-
713  int pairRank; // rank of corresponding chunk
-
714 
-
715  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
716  qureg.numQubitsRepresented, targetQubit);
-
717 
-
718  if (useLocalDataOnly){
-
719  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
720  } else {
-
721  // pack data to send to my pair process into the first half of pairStateVec
-
722  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
723 
-
724  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
725  qureg.numQubitsRepresented);
-
726  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
727  targetQubit, qureg.numQubitsRepresented);
-
728 
-
729  exchangePairStateVectorHalves(qureg, pairRank);
-
730  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
-
731  }
+

Definition at line 712 of file QuEST_cpu_distributed.c.

+
712  {
+
713  if (depolLevel == 0)
+
714  return;
+
715 
+
716  int rankIsUpper; // rank is in the upper half of an outer block
+
717  int pairRank; // rank of corresponding chunk
+
718 
+
719  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
720  qureg.numQubitsRepresented, targetQubit);
+
721 
+
722  if (useLocalDataOnly){
+
723  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
+
724  } else {
+
725  // pack data to send to my pair process into the first half of pairStateVec
+
726  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
+
727 
+
728  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
+
729  qureg.numQubitsRepresented);
+
730  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
+
731  targetQubit, qureg.numQubitsRepresented);
732 
-
733 }
+
733  exchangePairStateVectorHalves(qureg, pairRank);
+
734  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
+
735  }
+
736 
+
737 }
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, and Qureg::numQubitsRepresented.

+

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, and Qureg::numQubitsRepresented.

@@ -1431,100 +1431,100 @@

-

Definition at line 762 of file QuEST_cpu_distributed.c.

-
762  {
-
763  if (depolLevel == 0)
-
764  return;
-
765  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
-
766  int pairRank; // rank of corresponding chunk
-
767  int biggerQubit, smallerQubit;
-
768 
-
769  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
770 
-
771  qreal eta = 2/depolLevel;
-
772  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
773  qreal gamma = 1+delta;
-
774  gamma = 1/(gamma*gamma*gamma);
-
775  qreal GAMMA_PARTS_1_OR_2 = 1.0;
-
776  // TODO -- test delta too small
-
777  /*
-
778  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
-
779  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
-
780  exit(1);
-
781  }
-
782  */
-
783 
-
784  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
-
785  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
-
786  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
-
787 
-
788  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
789  qureg.numQubitsRepresented, biggerQubit);
-
790  if (useLocalDataOnlyBigQubit){
-
791  // does parts 1, 2 and 3 locally in one go
-
792  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
793  } else {
-
794  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
795  qureg.numQubitsRepresented, smallerQubit);
-
796  if (useLocalDataOnlySmallQubit){
-
797  // do part 1 locally
-
798  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
-
799 
-
800  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
-
801  // part 2 will be distributed and the value of the small qubit won't matter
-
802  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
803  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
804  qureg.numQubitsRepresented);
-
805  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
806  biggerQubit, qureg.numQubitsRepresented);
-
807 
-
808  exchangePairStateVectorHalves(qureg, pairRank);
-
809  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
810 
-
811  // part 3 will be distributed but involve rearranging for the smaller qubit
-
812  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
813  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
814  qureg.numQubitsRepresented);
-
815  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
816  biggerQubit, qureg.numQubitsRepresented);
-
817 
-
818  exchangePairStateVectorHalves(qureg, pairRank);
-
819  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
-
820  } else {
-
821  // do part 1, 2 and 3 distributed
-
822  // part 1
-
823  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
824  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
-
825  qureg.numQubitsRepresented);
-
826  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
827  smallerQubit, qureg.numQubitsRepresented);
-
828 
-
829  exchangePairStateVectorHalves(qureg, pairRank);
-
830  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
831 
-
832  // part 2
-
833  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
834  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
835  qureg.numQubitsRepresented);
-
836  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
837  biggerQubit, qureg.numQubitsRepresented);
-
838 
-
839  exchangePairStateVectorHalves(qureg, pairRank);
-
840  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
841 
-
842  // part 3
-
843  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
844  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
-
845  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
-
846  exchangePairStateVectorHalves(qureg, pairRank);
-
847  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
-
848 
-
849  }
-
850  }
-
851 
-
852 }
+

Definition at line 766 of file QuEST_cpu_distributed.c.

+
766  {
+
767  if (depolLevel == 0)
+
768  return;
+
769  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
+
770  int pairRank; // rank of corresponding chunk
+
771  int biggerQubit, smallerQubit;
+
772 
+
773  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
774 
+
775  qreal eta = 2/depolLevel;
+
776  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
+
777  qreal gamma = 1+delta;
+
778  gamma = 1/(gamma*gamma*gamma);
+
779  qreal GAMMA_PARTS_1_OR_2 = 1.0;
+
780  // TODO -- test delta too small
+
781  /*
+
782  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
+
783  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
+
784  exit(1);
+
785  }
+
786  */
+
787 
+
788  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
+
789  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
+
790  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
+
791 
+
792  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
793  qureg.numQubitsRepresented, biggerQubit);
+
794  if (useLocalDataOnlyBigQubit){
+
795  // does parts 1, 2 and 3 locally in one go
+
796  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
+
797  } else {
+
798  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
799  qureg.numQubitsRepresented, smallerQubit);
+
800  if (useLocalDataOnlySmallQubit){
+
801  // do part 1 locally
+
802  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
+
803 
+
804  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
+
805  // part 2 will be distributed and the value of the small qubit won't matter
+
806  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
807  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
808  qureg.numQubitsRepresented);
+
809  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
810  biggerQubit, qureg.numQubitsRepresented);
+
811 
+
812  exchangePairStateVectorHalves(qureg, pairRank);
+
813  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
814 
+
815  // part 3 will be distributed but involve rearranging for the smaller qubit
+
816  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
817  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
818  qureg.numQubitsRepresented);
+
819  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
820  biggerQubit, qureg.numQubitsRepresented);
+
821 
+
822  exchangePairStateVectorHalves(qureg, pairRank);
+
823  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
+
824  } else {
+
825  // do part 1, 2 and 3 distributed
+
826  // part 1
+
827  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
828  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
+
829  qureg.numQubitsRepresented);
+
830  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
831  smallerQubit, qureg.numQubitsRepresented);
+
832 
+
833  exchangePairStateVectorHalves(qureg, pairRank);
+
834  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
835 
+
836  // part 2
+
837  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
838  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
839  qureg.numQubitsRepresented);
+
840  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
841  biggerQubit, qureg.numQubitsRepresented);
+
842 
+
843  exchangePairStateVectorHalves(qureg, pairRank);
+
844  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
845 
+
846  // part 3
+
847  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
848  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
+
849  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
+
850  exchangePairStateVectorHalves(qureg, pairRank);
+
851  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
+
852 
+
853  }
+
854  }
+
855 
+
856 }
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForTwoQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), getChunkOuterBlockPairIdForPart3(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForTwoQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), getChunkOuterBlockPairIdForPart3(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

@@ -1554,43 +1554,43 @@

-

Definition at line 519 of file QuEST_cpu_distributed.c.

-
519  {
-
520  // MPI send/receive vars
-
521  int TAG=100;
-
522  MPI_Status status;
-
523  long long int numAmpsToSend = qureg.numAmpsPerChunk >> 1;
-
524 
-
525  // Multiple messages are required as MPI uses int rather than long long int for count
-
526  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
527  // to be safe
-
528  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
529  if (numAmpsToSend < maxMessageCount)
-
530  maxMessageCount = numAmpsToSend;
-
531 
-
532  // safely assume MPI_MAX... = 2^n, so division always exact
-
533  int numMessages = numAmpsToSend/maxMessageCount;
-
534  int i;
-
535  long long int offset;
-
536  // send the bottom half of my state vector to the top half of pairRank's qureg.pairStateVec
-
537  // receive pairRank's state vector into the top of qureg.pairStateVec
-
538  for (i=0; i<numMessages; i++){
-
539  offset = i*maxMessageCount;
-
540  MPI_Sendrecv(&qureg.pairStateVec.real[offset+numAmpsToSend], maxMessageCount,
-
541  MPI_QuEST_REAL, pairRank, TAG,
-
542  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
543  pairRank, TAG, MPI_COMM_WORLD, &status);
-
544  //printf("rank: %d err: %d\n", qureg.rank, err);
-
545  MPI_Sendrecv(&qureg.pairStateVec.imag[offset+numAmpsToSend], maxMessageCount,
-
546  MPI_QuEST_REAL, pairRank, TAG,
-
547  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
-
548  pairRank, TAG, MPI_COMM_WORLD, &status);
-
549  }
-
550 }
+

Definition at line 523 of file QuEST_cpu_distributed.c.

+
523  {
+
524  // MPI send/receive vars
+
525  int TAG=100;
+
526  MPI_Status status;
+
527  long long int numAmpsToSend = qureg.numAmpsPerChunk >> 1;
+
528 
+
529  // Multiple messages are required as MPI uses int rather than long long int for count
+
530  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
+
531  // to be safe
+
532  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
+
533  if (numAmpsToSend < maxMessageCount)
+
534  maxMessageCount = numAmpsToSend;
+
535 
+
536  // safely assume MPI_MAX... = 2^n, so division always exact
+
537  int numMessages = numAmpsToSend/maxMessageCount;
+
538  int i;
+
539  long long int offset;
+
540  // send the bottom half of my state vector to the top half of pairRank's qureg.pairStateVec
+
541  // receive pairRank's state vector into the top of qureg.pairStateVec
+
542  for (i=0; i<numMessages; i++){
+
543  offset = i*maxMessageCount;
+
544  MPI_Sendrecv(&qureg.pairStateVec.real[offset+numAmpsToSend], maxMessageCount,
+
545  MPI_QuEST_REAL, pairRank, TAG,
+
546  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
+
547  pairRank, TAG, MPI_COMM_WORLD, &status);
+
548  //printf("rank: %d err: %d\n", qureg.rank, err);
+
549  MPI_Sendrecv(&qureg.pairStateVec.imag[offset+numAmpsToSend], maxMessageCount,
+
550  MPI_QuEST_REAL, pairRank, TAG,
+
551  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
+
552  pairRank, TAG, MPI_COMM_WORLD, &status);
+
553  }
+
554 }

References Qureg::numAmpsPerChunk, and Qureg::pairStateVec.

-

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

@@ -1620,40 +1620,40 @@

-

Definition at line 489 of file QuEST_cpu_distributed.c.

-
489  {
-
490  // MPI send/receive vars
-
491  int TAG=100;
-
492  MPI_Status status;
-
493 
-
494  // Multiple messages are required as MPI uses int rather than long long int for count
-
495  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
496  // to be safe
-
497  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
498  if (qureg.numAmpsPerChunk < maxMessageCount)
-
499  maxMessageCount = qureg.numAmpsPerChunk;
-
500 
-
501  // safely assume MPI_MAX... = 2^n, so division always exact
-
502  int numMessages = qureg.numAmpsPerChunk/maxMessageCount;
-
503  int i;
-
504  long long int offset;
-
505  // send my state vector to pairRank's qureg.pairStateVec
-
506  // receive pairRank's state vector into qureg.pairStateVec
-
507  for (i=0; i<numMessages; i++){
-
508  offset = i*maxMessageCount;
-
509  MPI_Sendrecv(&qureg.stateVec.real[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
510  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
511  pairRank, TAG, MPI_COMM_WORLD, &status);
-
512  //printf("rank: %d err: %d\n", qureg.rank, err);
-
513  MPI_Sendrecv(&qureg.stateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
514  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
+

Definition at line 493 of file QuEST_cpu_distributed.c.

+
493  {
+
494  // MPI send/receive vars
+
495  int TAG=100;
+
496  MPI_Status status;
+
497 
+
498  // Multiple messages are required as MPI uses int rather than long long int for count
+
499  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
+
500  // to be safe
+
501  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
+
502  if (qureg.numAmpsPerChunk < maxMessageCount)
+
503  maxMessageCount = qureg.numAmpsPerChunk;
+
504 
+
505  // safely assume MPI_MAX... = 2^n, so division always exact
+
506  int numMessages = qureg.numAmpsPerChunk/maxMessageCount;
+
507  int i;
+
508  long long int offset;
+
509  // send my state vector to pairRank's qureg.pairStateVec
+
510  // receive pairRank's state vector into qureg.pairStateVec
+
511  for (i=0; i<numMessages; i++){
+
512  offset = i*maxMessageCount;
+
513  MPI_Sendrecv(&qureg.stateVec.real[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
+
514  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
515  pairRank, TAG, MPI_COMM_WORLD, &status);
-
516  }
-
517 }
+
516  //printf("rank: %d err: %d\n", qureg.rank, err);
+
517  MPI_Sendrecv(&qureg.stateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
+
518  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
+
519  pairRank, TAG, MPI_COMM_WORLD, &status);
+
520  }
+
521 }

References Qureg::numAmpsPerChunk, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_swapQubitAmps(), and statevec_unitary().

+

Referenced by statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_swapQubitAmps(), and statevec_unitary().

@@ -1691,14 +1691,14 @@

-

Definition at line 204 of file QuEST_cpu_distributed.c.

-
204  {
-
205  return index/qureg.numAmpsPerChunk; // this is numAmpsPerChunk
-
206 }
+

Definition at line 208 of file QuEST_cpu_distributed.c.

+
208  {
+
209  return index/qureg.numAmpsPerChunk; // this is numAmpsPerChunk
+
210 }

References Qureg::numAmpsPerChunk.

-

Referenced by statevec_getImagAmp(), and statevec_getRealAmp().

+

Referenced by statevec_getImagAmp(), and statevec_getRealAmp().

@@ -1754,20 +1754,20 @@

-

Definition at line 324 of file QuEST_cpu_distributed.c.

-
325 {
-
326  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
327  int chunksPerOuterHalfBlock = sizeOuterHalfBlock/chunkSize;
-
328  if (chunkIsUpper){
-
329  return chunkId + chunksPerOuterHalfBlock;
-
330  } else {
-
331  return chunkId - chunksPerOuterHalfBlock;
-
332  }
-
333 }
+

Definition at line 328 of file QuEST_cpu_distributed.c.

+
329 {
+
330  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
+
331  int chunksPerOuterHalfBlock = sizeOuterHalfBlock/chunkSize;
+
332  if (chunkIsUpper){
+
333  return chunkId + chunksPerOuterHalfBlock;
+
334  } else {
+
335  return chunkId - chunksPerOuterHalfBlock;
+
336  }
+
337 }
-

References chunkIsUpper().

+

References chunkIsUpper().

-

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixDamping(), densmatr_mixDepolarising(), and densmatr_mixTwoQubitDepolarising().

@@ -1835,29 +1835,29 @@

-

Definition at line 335 of file QuEST_cpu_distributed.c.

-
337 {
-
338  long long int sizeOuterHalfBlockBiggerQubit = 1LL << (biggerQubit+numQubits);
-
339  long long int sizeOuterHalfBlockSmallerQubit = 1LL << (smallerQubit+numQubits);
-
340  int chunksPerOuterHalfBlockSmallerQubit = sizeOuterHalfBlockSmallerQubit/chunkSize;
-
341  int chunksPerOuterHalfBlockBiggerQubit = sizeOuterHalfBlockBiggerQubit/chunkSize;
-
342  int rank;
-
343  if (chunkIsUpperBiggerQubit){
-
344  rank = chunkId + chunksPerOuterHalfBlockBiggerQubit;
-
345  } else {
-
346  rank = chunkId - chunksPerOuterHalfBlockBiggerQubit;
-
347  }
-
348 
-
349  if (chunkIsUpperSmallerQubit){
-
350  rank = rank + chunksPerOuterHalfBlockSmallerQubit;
-
351  } else {
-
352  rank = rank - chunksPerOuterHalfBlockSmallerQubit;
-
353  }
-
354 
-
355  return rank;
-
356 }
+

Definition at line 339 of file QuEST_cpu_distributed.c.

+
341 {
+
342  long long int sizeOuterHalfBlockBiggerQubit = 1LL << (biggerQubit+numQubits);
+
343  long long int sizeOuterHalfBlockSmallerQubit = 1LL << (smallerQubit+numQubits);
+
344  int chunksPerOuterHalfBlockSmallerQubit = sizeOuterHalfBlockSmallerQubit/chunkSize;
+
345  int chunksPerOuterHalfBlockBiggerQubit = sizeOuterHalfBlockBiggerQubit/chunkSize;
+
346  int rank;
+
347  if (chunkIsUpperBiggerQubit){
+
348  rank = chunkId + chunksPerOuterHalfBlockBiggerQubit;
+
349  } else {
+
350  rank = chunkId - chunksPerOuterHalfBlockBiggerQubit;
+
351  }
+
352 
+
353  if (chunkIsUpperSmallerQubit){
+
354  rank = rank + chunksPerOuterHalfBlockSmallerQubit;
+
355  } else {
+
356  rank = rank - chunksPerOuterHalfBlockSmallerQubit;
+
357  }
+
358 
+
359  return rank;
+
360 }
-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -1919,20 +1919,20 @@

Returns
chunkId of chunk required to rotate targetQubit
-

Definition at line 313 of file QuEST_cpu_distributed.c.

-
314 {
-
315  long long int sizeHalfBlock = 1LL << (targetQubit);
-
316  int chunksPerHalfBlock = sizeHalfBlock/chunkSize;
-
317  if (chunkIsUpper){
-
318  return chunkId + chunksPerHalfBlock;
-
319  } else {
-
320  return chunkId - chunksPerHalfBlock;
-
321  }
-
322 }
+

Definition at line 317 of file QuEST_cpu_distributed.c.

+
318 {
+
319  long long int sizeHalfBlock = 1LL << (targetQubit);
+
320  int chunksPerHalfBlock = sizeHalfBlock/chunkSize;
+
321  if (chunkIsUpper){
+
322  return chunkId + chunksPerHalfBlock;
+
323  } else {
+
324  return chunkId - chunksPerHalfBlock;
+
325  }
+
326 }
-

References chunkIsUpper().

+

References chunkIsUpper().

-

Referenced by statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), and statevec_unitary().

+

Referenced by statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_hadamard(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), and statevec_unitary().

@@ -1970,29 +1970,29 @@

Definition at line 1401 of file QuEST_cpu_distributed.c.

-
1401  {
-
1402  long long int chunkStartInd = qureg.numAmpsPerChunk * qureg.chunkId;
-
1403  long long int chunkEndInd = chunkStartInd + qureg.numAmpsPerChunk; // exclusive
-
1404  long long int oddParityInd;
-
1405 
-
1406  if (extractBit(qb1, chunkStartInd) != extractBit(qb2, chunkStartInd))
-
1407  return chunkStartInd;
-
1408 
-
1409  oddParityInd = flipBit(chunkStartInd, qb1);
-
1410  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1411  return oddParityInd;
-
1412 
-
1413  oddParityInd = flipBit(chunkStartInd, qb2);
-
1414  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1415  return oddParityInd;
+

Definition at line 1412 of file QuEST_cpu_distributed.c.

+
1412  {
+
1413  long long int chunkStartInd = qureg.numAmpsPerChunk * qureg.chunkId;
+
1414  long long int chunkEndInd = chunkStartInd + qureg.numAmpsPerChunk; // exclusive
+
1415  long long int oddParityInd;
1416 
-
1417  return -1;
-
1418 }
+
1417  if (extractBit(qb1, chunkStartInd) != extractBit(qb2, chunkStartInd))
+
1418  return chunkStartInd;
+
1419 
+
1420  oddParityInd = flipBit(chunkStartInd, qb1);
+
1421  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
+
1422  return oddParityInd;
+
1423 
+
1424  oddParityInd = flipBit(chunkStartInd, qb2);
+
1425  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
+
1426  return oddParityInd;
+
1427 
+
1428  return -1;
+
1429 }

References Qureg::chunkId, extractBit(), flipBit(), and Qureg::numAmpsPerChunk.

-

Referenced by statevec_swapQubitAmps().

+

Referenced by statevec_swapQubitAmps().

@@ -2060,21 +2060,21 @@

Definition at line 268 of file QuEST_cpu_distributed.c.

-
269 {
-
270  if (chunkIsUpper){
-
271  *rot1=alpha;
-
272  rot2->real=-beta.real;
-
273  rot2->imag=-beta.imag;
-
274  } else {
-
275  *rot1=beta;
-
276  *rot2=alpha;
-
277  }
-
278 }
+

Definition at line 272 of file QuEST_cpu_distributed.c.

+
273 {
+
274  if (chunkIsUpper){
+
275  *rot1=alpha;
+
276  rot2->real=-beta.real;
+
277  rot2->imag=-beta.imag;
+
278  } else {
+
279  *rot1=beta;
+
280  *rot2=alpha;
+
281  }
+
282 }
-

References chunkIsUpper(), Complex::imag, and Complex::real.

+

References chunkIsUpper(), Complex::imag, and Complex::real.

-

Referenced by statevec_compactUnitary(), and statevec_controlledCompactUnitary().

+

Referenced by statevec_compactUnitary(), and statevec_controlledCompactUnitary().

@@ -2136,20 +2136,20 @@

Definition at line 293 of file QuEST_cpu_distributed.c.

-
294 {
-
295  if (chunkIsUpper){
-
296  *rot1=(Complex) {.real=u.real[0][0], .imag=u.imag[0][0]};
-
297  *rot2=(Complex) {.real=u.real[0][1], .imag=u.imag[0][1]};
-
298  } else {
-
299  *rot1=(Complex) {.real=u.real[1][0], .imag=u.imag[1][0]};
-
300  *rot2=(Complex) {.real=u.real[1][1], .imag=u.imag[1][1]};
-
301  }
-
302 }
+

Definition at line 297 of file QuEST_cpu_distributed.c.

+
298 {
+
299  if (chunkIsUpper){
+
300  *rot1=(Complex) {.real=u.real[0][0], .imag=u.imag[0][0]};
+
301  *rot2=(Complex) {.real=u.real[0][1], .imag=u.imag[0][1]};
+
302  } else {
+
303  *rot1=(Complex) {.real=u.real[1][0], .imag=u.imag[1][0]};
+
304  *rot2=(Complex) {.real=u.real[1][1], .imag=u.imag[1][1]};
+
305  }
+
306 }
-

References chunkIsUpper(), ComplexMatrix2::imag, Complex::real, and ComplexMatrix2::real.

+

References chunkIsUpper(), ComplexMatrix2::imag, Complex::real, and ComplexMatrix2::real.

-

Referenced by statevec_controlledUnitary(), statevec_multiControlledUnitary(), and statevec_unitary().

+

Referenced by statevec_controlledUnitary(), statevec_multiControlledUnitary(), and statevec_unitary().

@@ -2197,14 +2197,14 @@

Returns
1: one chunk fits in one block 0: chunk is larger than block fix – this should be renamed to matrixBlockFitsInChunk
-

Definition at line 366 of file QuEST_cpu_distributed.c.

- @@ -2260,16 +2260,16 @@

Returns
int – 1: skip, 0: don't skip
-

Definition at line 1299 of file QuEST_cpu_distributed.c.

-
1300 {
-
1301  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1302  int numChunksToSkip = sizeHalfBlock/chunkSize;
-
1303  // calculate probability by summing over numChunksToSkip, then skipping numChunksToSkip, etc
-
1304  int bitToCheck = chunkId & numChunksToSkip;
-
1305  return bitToCheck;
-
1306 }
+

Definition at line 1303 of file QuEST_cpu_distributed.c.

+
1304 {
+
1305  long long int sizeHalfBlock = 1LL << (measureQubit);
+
1306  int numChunksToSkip = sizeHalfBlock/chunkSize;
+
1307  // calculate probability by summing over numChunksToSkip, then skipping numChunksToSkip, etc
+
1308  int bitToCheck = chunkId & numChunksToSkip;
+
1309  return bitToCheck;
+
1310 }
-

Referenced by statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

@@ -2299,26 +2299,26 @@

-

Definition at line 1589 of file QuEST_cpu_distributed.c.

-
1589  {
-
1590 
-
1591  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
-
1592  if (qureg.numChunks == 1)
-
1593  return localExpec;
-
1594 
-
1595  qreal localReal = localExpec.real;
-
1596  qreal localImag = localExpec.imag;
-
1597  qreal globalReal, globalImag;
-
1598  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1599  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1600 
-
1601  Complex globalExpec;
-
1602  globalExpec.real = globalReal;
-
1603  globalExpec.imag = globalImag;
-
1604  return globalExpec;
-
1605 }
+

Definition at line 1600 of file QuEST_cpu_distributed.c.

+
1600  {
+
1601 
+
1602  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
+
1603  if (qureg.numChunks == 1)
+
1604  return localExpec;
+
1605 
+
1606  qreal localReal = localExpec.real;
+
1607  qreal localImag = localExpec.imag;
+
1608  qreal globalReal, globalImag;
+
1609  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1610  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1611 
+
1612  Complex globalExpec;
+
1613  globalExpec.real = globalReal;
+
1614  globalExpec.imag = globalImag;
+
1615  return globalExpec;
+
1616 }
-

References Complex::imag, Qureg::numChunks, qreal, Complex::real, and statevec_calcExpecDiagonalOpLocal().

+

References Complex::imag, Qureg::numChunks, qreal, Complex::real, and statevec_calcExpecDiagonalOpLocal().

@@ -2367,7 +2367,7 @@

50  return globalInnerProd;
51 }
-

References Complex::imag, Qureg::numChunks, qreal, Complex::real, and statevec_calcInnerProductLocal().

+

References Complex::imag, Qureg::numChunks, qreal, Complex::real, and statevec_calcInnerProductLocal().

@@ -2409,17 +2409,17 @@

-

Definition at line 1336 of file QuEST_cpu_distributed.c.

-
1336  {
-
1337 
-
1338  // each node populates retProbs with contributions from the subset of amps in each
-
1339  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
1340 
-
1341  // then, retProbs are summed element-wise
-
1342  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1343 }
+

Definition at line 1340 of file QuEST_cpu_distributed.c.

+
1340  {
+
1341 
+
1342  // each node populates retProbs with contributions from the subset of amps in each
+
1343  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
1344 
+
1345  // then, retProbs are summed element-wise
+
1346  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1347 }
-

References statevec_calcProbOfAllOutcomesLocal().

+

References statevec_calcProbOfAllOutcomesLocal().

@@ -2455,23 +2455,23 @@

-

Definition at line 1308 of file QuEST_cpu_distributed.c.

-
1309 {
-
1310  qreal stateProb=0, totalStateProb=0;
-
1311  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1312  if (skipValuesWithinRank) {
-
1313  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1314  } else {
-
1315  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1316  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
-
1317  } else stateProb = 0;
-
1318  }
-
1319  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1320  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
-
1321  return totalStateProb;
-
1322 }
+

Definition at line 1312 of file QuEST_cpu_distributed.c.

+
1313 {
+
1314  qreal stateProb=0, totalStateProb=0;
+
1315  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
+
1316  if (skipValuesWithinRank) {
+
1317  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
+
1318  } else {
+
1319  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
+
1320  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
+
1321  } else stateProb = 0;
+
1322  }
+
1323  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1324  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
+
1325  return totalStateProb;
+
1326 }
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_findProbabilityOfZeroDistributed(), and statevec_findProbabilityOfZeroLocal().

+

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_findProbabilityOfZeroDistributed(), and statevec_findProbabilityOfZeroLocal().

@@ -2565,27 +2565,27 @@

-

Definition at line 1364 of file QuEST_cpu_distributed.c.

-
1365 {
-
1366  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1367  if (skipValuesWithinRank) {
-
1368  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
-
1369  } else {
-
1370  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1371  // chunk has amps for q=0
-
1372  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1373  totalStateProb);
- -
1375  } else {
-
1376  // chunk has amps for q=1
-
1377  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1378  totalStateProb);
- -
1380  }
-
1381  }
-
1382 }
+

Definition at line 1368 of file QuEST_cpu_distributed.c.

+
1369 {
+
1370  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
+
1371  if (skipValuesWithinRank) {
+
1372  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
+
1373  } else {
+
1374  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
+
1375  // chunk has amps for q=0
+
1376  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
+
1377  totalStateProb);
+ +
1379  } else {
+
1380  // chunk has amps for q=1
+
1381  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
+
1382  totalStateProb);
+ +
1384  }
+
1385  }
+
1386 }
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), and statevec_collapseToOutcomeDistributedSetZero().

+

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), and statevec_collapseToOutcomeDistributedSetZero().

@@ -2627,44 +2627,44 @@

-

Definition at line 854 of file QuEST_cpu_distributed.c.

-
855 {
-
856  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
857  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
858  Complex rot1, rot2;
-
859 
-
860  // rank's chunk is in upper half of block
-
861  int rankIsUpper;
-
862  int pairRank; // rank of corresponding chunk
+

Definition at line 858 of file QuEST_cpu_distributed.c.

+
859 {
+
860  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
861  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
862  Complex rot1, rot2;
863 
-
864  if (useLocalDataOnly){
-
865  // all values required to update state vector lie in this rank
-
866  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
867  } else {
-
868  // need to get corresponding chunk of state vector from other rank
-
869  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
870  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
871  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
872  // get corresponding values from my pair
-
873  exchangeStateVectors(qureg, pairRank);
-
874 
-
875  // this rank's values are either in the upper of lower half of the block.
-
876  // send values to compactUnitaryDistributed in the correct order
-
877  if (rankIsUpper){
-
878  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
879  qureg.stateVec, //upper
-
880  qureg.pairStateVec, //lower
-
881  qureg.stateVec); //output
-
882  } else {
-
883  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
884  qureg.pairStateVec, //upper
-
885  qureg.stateVec, //lower
-
886  qureg.stateVec); //output
-
887  }
-
888  }
-
889 }
+
864  // rank's chunk is in upper half of block
+
865  int rankIsUpper;
+
866  int pairRank; // rank of corresponding chunk
+
867 
+
868  if (useLocalDataOnly){
+
869  // all values required to update state vector lie in this rank
+
870  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
+
871  } else {
+
872  // need to get corresponding chunk of state vector from other rank
+
873  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
874  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
+
875  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
876  // get corresponding values from my pair
+
877  exchangeStateVectors(qureg, pairRank);
+
878 
+
879  // this rank's values are either in the upper of lower half of the block.
+
880  // send values to compactUnitaryDistributed in the correct order
+
881  if (rankIsUpper){
+
882  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
+
883  qureg.stateVec, //upper
+
884  qureg.pairStateVec, //lower
+
885  qureg.stateVec); //output
+
886  } else {
+
887  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
+
888  qureg.pairStateVec, //upper
+
889  qureg.stateVec, //lower
+
890  qureg.stateVec); //output
+
891  }
+
892  }
+
893 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_compactUnitaryDistributed(), and statevec_compactUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_compactUnitaryDistributed(), and statevec_compactUnitaryLocal().

@@ -2712,45 +2712,45 @@

-

Definition at line 930 of file QuEST_cpu_distributed.c.

-
931 {
-
932  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
933  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
934  Complex rot1, rot2;
-
935 
-
936  // rank's chunk is in upper half of block
-
937  int rankIsUpper;
-
938  int pairRank; // rank of corresponding chunk
+

Definition at line 934 of file QuEST_cpu_distributed.c.

+
935 {
+
936  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
937  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
938  Complex rot1, rot2;
939 
-
940  if (useLocalDataOnly){
-
941  // all values required to update state vector lie in this rank
-
942  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
943  } else {
-
944  // need to get corresponding chunk of state vector from other rank
-
945  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
946  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
947  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
948  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
949  // get corresponding values from my pair
-
950  exchangeStateVectors(qureg, pairRank);
-
951 
-
952  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
-
953  // in the correct order
-
954  if (rankIsUpper){
-
955  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
956  qureg.stateVec, //upper
-
957  qureg.pairStateVec, //lower
-
958  qureg.stateVec); //output
-
959  } else {
-
960  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
961  qureg.pairStateVec, //upper
-
962  qureg.stateVec, //lower
-
963  qureg.stateVec); //output
-
964  }
-
965  }
-
966 }
+
940  // rank's chunk is in upper half of block
+
941  int rankIsUpper;
+
942  int pairRank; // rank of corresponding chunk
+
943 
+
944  if (useLocalDataOnly){
+
945  // all values required to update state vector lie in this rank
+
946  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
+
947  } else {
+
948  // need to get corresponding chunk of state vector from other rank
+
949  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
950  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
+
951  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
952  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
953  // get corresponding values from my pair
+
954  exchangeStateVectors(qureg, pairRank);
+
955 
+
956  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
+
957  // in the correct order
+
958  if (rankIsUpper){
+
959  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
960  qureg.stateVec, //upper
+
961  qureg.pairStateVec, //lower
+
962  qureg.stateVec); //output
+
963  } else {
+
964  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
965  qureg.pairStateVec, //upper
+
966  qureg.stateVec, //lower
+
967  qureg.stateVec); //output
+
968  }
+
969  }
+
970 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledCompactUnitaryDistributed(), and statevec_controlledCompactUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledCompactUnitaryDistributed(), and statevec_controlledCompactUnitaryLocal().

@@ -2786,29 +2786,29 @@

-

Definition at line 1071 of file QuEST_cpu_distributed.c.

-
1072 {
-
1073  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1074  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1075  int rankIsUpper; // rank's chunk is in upper half of block
-
1076  int pairRank; // rank of corresponding chunk
-
1077 
-
1078  if (useLocalDataOnly){
-
1079  // all values required to update state vector lie in this rank
-
1080  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
1081  } else {
-
1082  // need to get corresponding chunk of state vector from other rank
-
1083  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1084  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1085  // get corresponding values from my pair
-
1086  exchangeStateVectors(qureg, pairRank);
-
1087  statevec_controlledNotDistributed(qureg,controlQubit,
-
1088  qureg.pairStateVec, //in
-
1089  qureg.stateVec); //out
-
1090  }
-
1091 }
+

Definition at line 1075 of file QuEST_cpu_distributed.c.

+
1076 {
+
1077  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1078  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1079  int rankIsUpper; // rank's chunk is in upper half of block
+
1080  int pairRank; // rank of corresponding chunk
+
1081 
+
1082  if (useLocalDataOnly){
+
1083  // all values required to update state vector lie in this rank
+
1084  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
+
1085  } else {
+
1086  // need to get corresponding chunk of state vector from other rank
+
1087  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1088  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1089  // get corresponding values from my pair
+
1090  exchangeStateVectors(qureg, pairRank);
+
1091  statevec_controlledNotDistributed(qureg,controlQubit,
+
1092  qureg.pairStateVec, //in
+
1093  qureg.stateVec); //out
+
1094  }
+
1095 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledNotDistributed(), and statevec_controlledNotLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledNotDistributed(), and statevec_controlledNotLocal().

@@ -2844,40 +2844,40 @@

-

Definition at line 1188 of file QuEST_cpu_distributed.c.

-
1189 {
-
1190  int conjFac = 1;
-
1191 
-
1192  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1193  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1194  int rankIsUpper; // rank's chunk is in upper half of block
-
1195  int pairRank; // rank of corresponding chunk
-
1196 
-
1197  if (useLocalDataOnly){
-
1198  // all values required to update state vector lie in this rank
-
1199  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1200  } else {
-
1201  // need to get corresponding chunk of state vector from other rank
-
1202  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1203  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1204  // get corresponding values from my pair
-
1205  exchangeStateVectors(qureg, pairRank);
-
1206  // this rank's values are either in the upper of lower half of the block
-
1207  if (rankIsUpper){
-
1208  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1209  qureg.pairStateVec, //in
-
1210  qureg.stateVec,
-
1211  conjFac); //out
-
1212  } else {
-
1213  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1214  qureg.pairStateVec, //in
-
1215  qureg.stateVec,
-
1216  - conjFac); //out
-
1217  }
-
1218  }
-
1219 }
+

Definition at line 1192 of file QuEST_cpu_distributed.c.

+
1193 {
+
1194  int conjFac = 1;
+
1195 
+
1196  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1197  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1198  int rankIsUpper; // rank's chunk is in upper half of block
+
1199  int pairRank; // rank of corresponding chunk
+
1200 
+
1201  if (useLocalDataOnly){
+
1202  // all values required to update state vector lie in this rank
+
1203  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
1204  } else {
+
1205  // need to get corresponding chunk of state vector from other rank
+
1206  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1207  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1208  // get corresponding values from my pair
+
1209  exchangeStateVectors(qureg, pairRank);
+
1210  // this rank's values are either in the upper of lower half of the block
+
1211  if (rankIsUpper){
+
1212  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1213  qureg.pairStateVec, //in
+
1214  qureg.stateVec,
+
1215  conjFac); //out
+
1216  } else {
+
1217  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1218  qureg.pairStateVec, //in
+
1219  qureg.stateVec,
+
1220  - conjFac); //out
+
1221  }
+
1222  }
+
1223 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

@@ -2913,40 +2913,40 @@

-

Definition at line 1221 of file QuEST_cpu_distributed.c.

-
1222 {
-
1223  int conjFac = -1;
-
1224 
-
1225  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1226  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1227  int rankIsUpper; // rank's chunk is in upper half of block
-
1228  int pairRank; // rank of corresponding chunk
-
1229 
-
1230  if (useLocalDataOnly){
-
1231  // all values required to update state vector lie in this rank
-
1232  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1233  } else {
-
1234  // need to get corresponding chunk of state vector from other rank
-
1235  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1236  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1237  // get corresponding values from my pair
-
1238  exchangeStateVectors(qureg, pairRank);
-
1239  // this rank's values are either in the upper of lower half of the block
-
1240  if (rankIsUpper){
-
1241  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1242  qureg.pairStateVec, //in
-
1243  qureg.stateVec,
-
1244  conjFac); //out
-
1245  } else {
-
1246  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1247  qureg.pairStateVec, //in
-
1248  qureg.stateVec,
-
1249  - conjFac); //out
-
1250  }
-
1251  }
-
1252 }
+

Definition at line 1225 of file QuEST_cpu_distributed.c.

+
1226 {
+
1227  int conjFac = -1;
+
1228 
+
1229  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1230  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1231  int rankIsUpper; // rank's chunk is in upper half of block
+
1232  int pairRank; // rank of corresponding chunk
+
1233 
+
1234  if (useLocalDataOnly){
+
1235  // all values required to update state vector lie in this rank
+
1236  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
1237  } else {
+
1238  // need to get corresponding chunk of state vector from other rank
+
1239  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1240  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1241  // get corresponding values from my pair
+
1242  exchangeStateVectors(qureg, pairRank);
+
1243  // this rank's values are either in the upper of lower half of the block
+
1244  if (rankIsUpper){
+
1245  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1246  qureg.pairStateVec, //in
+
1247  qureg.stateVec,
+
1248  conjFac); //out
+
1249  } else {
+
1250  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1251  qureg.pairStateVec, //in
+
1252  qureg.stateVec,
+
1253  - conjFac); //out
+
1254  }
+
1255  }
+
1256 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

@@ -2988,45 +2988,45 @@

-

Definition at line 968 of file QuEST_cpu_distributed.c.

-
970 {
-
971  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
972  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
973  Complex rot1, rot2;
-
974 
-
975  // rank's chunk is in upper half of block
-
976  int rankIsUpper;
-
977  int pairRank; // rank of corresponding chunk
+

Definition at line 972 of file QuEST_cpu_distributed.c.

+
974 {
+
975  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
976  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
977  Complex rot1, rot2;
978 
-
979  if (useLocalDataOnly){
-
980  // all values required to update state vector lie in this rank
-
981  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
982  } else {
-
983  // need to get corresponding chunk of state vector from other rank
-
984  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
985  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
986  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
987  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
988  // get corresponding values from my pair
-
989  exchangeStateVectors(qureg, pairRank);
-
990 
-
991  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
-
992  // in the correct order
-
993  if (rankIsUpper){
-
994  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
995  qureg.stateVec, //upper
-
996  qureg.pairStateVec, //lower
-
997  qureg.stateVec); //output
-
998  } else {
-
999  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
1000  qureg.pairStateVec, //upper
-
1001  qureg.stateVec, //lower
-
1002  qureg.stateVec); //output
-
1003  }
-
1004  }
-
1005 }
+
979  // rank's chunk is in upper half of block
+
980  int rankIsUpper;
+
981  int pairRank; // rank of corresponding chunk
+
982 
+
983  if (useLocalDataOnly){
+
984  // all values required to update state vector lie in this rank
+
985  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
+
986  } else {
+
987  // need to get corresponding chunk of state vector from other rank
+
988  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
989  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
990  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
991  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
992  // get corresponding values from my pair
+
993  exchangeStateVectors(qureg, pairRank);
+
994 
+
995  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
+
996  // in the correct order
+
997  if (rankIsUpper){
+
998  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
999  qureg.stateVec, //upper
+
1000  qureg.pairStateVec, //lower
+
1001  qureg.stateVec); //output
+
1002  } else {
+
1003  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
1004  qureg.pairStateVec, //upper
+
1005  qureg.stateVec, //lower
+
1006  qureg.stateVec); //output
+
1007  }
+
1008  }
+
1009 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

@@ -3056,18 +3056,18 @@

-

Definition at line 218 of file QuEST_cpu_distributed.c.

-
218  {
-
219  int chunkId = getChunkIdFromIndex(qureg, index);
-
220  qreal el;
-
221  if (qureg.chunkId==chunkId){
-
222  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
-
223  }
-
224  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
225  return el;
-
226 }
+

Definition at line 222 of file QuEST_cpu_distributed.c.

+
222  {
+
223  int chunkId = getChunkIdFromIndex(qureg, index);
+
224  qreal el;
+
225  if (qureg.chunkId==chunkId){
+
226  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
+
227  }
+
228  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
+
229  return el;
+
230 }
-

References Qureg::chunkId, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -3097,18 +3097,18 @@

-

Definition at line 208 of file QuEST_cpu_distributed.c.

-
208  {
-
209  int chunkId = getChunkIdFromIndex(qureg, index);
-
210  qreal el;
-
211  if (qureg.chunkId==chunkId){
-
212  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
-
213  }
-
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
215  return el;
-
216 }
+

Definition at line 212 of file QuEST_cpu_distributed.c.

+
212  {
+
213  int chunkId = getChunkIdFromIndex(qureg, index);
+
214  qreal el;
+
215  if (qureg.chunkId==chunkId){
+
216  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
+
217  }
+
218  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
+
219  return el;
+
220 }
-

References Qureg::chunkId, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -3138,42 +3138,42 @@

-

Definition at line 1254 of file QuEST_cpu_distributed.c.

-
1255 {
-
1256  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1257  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1258 
-
1259  // rank's chunk is in upper half of block
-
1260  int rankIsUpper;
-
1261  int pairRank; // rank of corresponding chunk
+

Definition at line 1258 of file QuEST_cpu_distributed.c.

+
1259 {
+
1260  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1261  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1262 
-
1263  if (useLocalDataOnly){
-
1264  // all values required to update state vector lie in this rank
-
1265  statevec_hadamardLocal(qureg, targetQubit);
-
1266  } else {
-
1267  // need to get corresponding chunk of state vector from other rank
-
1268  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1269  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1270  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1271  // get corresponding values from my pair
-
1272  exchangeStateVectors(qureg, pairRank);
-
1273  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
-
1274  // in the correct order
-
1275  if (rankIsUpper){
- -
1277  qureg.stateVec, //upper
-
1278  qureg.pairStateVec, //lower
-
1279  qureg.stateVec, rankIsUpper); //output
-
1280  } else {
- -
1282  qureg.pairStateVec, //upper
-
1283  qureg.stateVec, //lower
-
1284  qureg.stateVec, rankIsUpper); //output
-
1285  }
-
1286  }
-
1287 }
+
1263  // rank's chunk is in upper half of block
+
1264  int rankIsUpper;
+
1265  int pairRank; // rank of corresponding chunk
+
1266 
+
1267  if (useLocalDataOnly){
+
1268  // all values required to update state vector lie in this rank
+
1269  statevec_hadamardLocal(qureg, targetQubit);
+
1270  } else {
+
1271  // need to get corresponding chunk of state vector from other rank
+
1272  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1273  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1274  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
1275  // get corresponding values from my pair
+
1276  exchangeStateVectors(qureg, pairRank);
+
1277  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
+
1278  // in the correct order
+
1279  if (rankIsUpper){
+ +
1281  qureg.stateVec, //upper
+
1282  qureg.pairStateVec, //lower
+
1283  qureg.stateVec, rankIsUpper); //output
+
1284  } else {
+ +
1286  qureg.pairStateVec, //upper
+
1287  qureg.stateVec, //lower
+
1288  qureg.stateVec, rankIsUpper); //output
+
1289  }
+
1290  }
+
1291 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

@@ -3209,52 +3209,52 @@

-

Definition at line 1093 of file QuEST_cpu_distributed.c.

-
1094 {
-
1095  /* operation is the same regardless of control and target ordering, hence
-
1096  * we accept only bitMasks (for convenience of caller, when shifting qubits
-
1097  * for density matrices)
-
1098  */
-
1099 
-
1100  // global index of the first basis state in this node
-
1101  long long int firstInd = qureg.chunkId * qureg.numAmpsPerChunk;
-
1102 
-
1103  /* optimisation: if this node doesn't contain any amplitudes for which {ctrls}={1}
-
1104  * (and hence, neither does the pair node), then these pair nodes have nothing to modify
-
1105  * nor any need to communicate, and can halt. No ctrls are contained in the node
-
1106  * if the distance from the first index, to the next index where {ctrls}=1, is
-
1107  * greater than the total contained amplitudes. This is a worthwhile optimisation,
-
1108  * since although we must still wait for the slowest node, we have potentially reduced
-
1109  * the network traffic and might avoid saturation.
-
1110  */
-
1111  if ((firstInd|ctrlMask) - firstInd >= qureg.numAmpsPerChunk)
-
1112  return;
-
1113 
-
1114  /* nodes communicate pairwise, and (ignoring ctrls) swap all their amplitudes with mate.
-
1115  * hence we find |pairState> = X_{targs}|firstStateInNode>, determine which node contains
-
1116  * |pairState>, and swap state-vector with it (unless it happens to be this node).
-
1117  */
-
1118 
-
1119  // global index of the corresponding NOT'd first basis state
-
1120  long long int pairInd = firstInd ^ targMask;
-
1121  int pairRank = pairInd / qureg.numAmpsPerChunk;
-
1122  int useLocalDataOnly = (pairRank == qureg.chunkId);
-
1123 
-
1124  if (useLocalDataOnly) {
-
1125  // swaps amplitudes locally, setting |a>=X|b>, and |b>=X|a>
-
1126  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
-
1127  } else {
-
1128  // swaps amplitudes with pair node
-
1129  exchangeStateVectors(qureg, pairRank);
-
1130  // modifies only |a>=X|b> (pair node handles the converse)
- -
1132  qureg, ctrlMask, targMask,
-
1133  qureg.pairStateVec, // in
-
1134  qureg.stateVec); // out
-
1135  }
-
1136 }
+

Definition at line 1097 of file QuEST_cpu_distributed.c.

+
1098 {
+
1099  /* operation is the same regardless of control and target ordering, hence
+
1100  * we accept only bitMasks (for convenience of caller, when shifting qubits
+
1101  * for density matrices)
+
1102  */
+
1103 
+
1104  // global index of the first basis state in this node
+
1105  long long int firstInd = qureg.chunkId * qureg.numAmpsPerChunk;
+
1106 
+
1107  /* optimisation: if this node doesn't contain any amplitudes for which {ctrls}={1}
+
1108  * (and hence, neither does the pair node), then these pair nodes have nothing to modify
+
1109  * nor any need to communicate, and can halt. No ctrls are contained in the node
+
1110  * if the distance from the first index, to the next index where {ctrls}=1, is
+
1111  * greater than the total contained amplitudes. This is a worthwhile optimisation,
+
1112  * since although we must still wait for the slowest node, we have potentially reduced
+
1113  * the network traffic and might avoid saturation.
+
1114  */
+
1115  if ((firstInd|ctrlMask) - firstInd >= qureg.numAmpsPerChunk)
+
1116  return;
+
1117 
+
1118  /* nodes communicate pairwise, and (ignoring ctrls) swap all their amplitudes with mate.
+
1119  * hence we find |pairState> = X_{targs}|firstStateInNode>, determine which node contains
+
1120  * |pairState>, and swap state-vector with it (unless it happens to be this node).
+
1121  */
+
1122 
+
1123  // global index of the corresponding NOT'd first basis state
+
1124  long long int pairInd = firstInd ^ targMask;
+
1125  int pairRank = pairInd / qureg.numAmpsPerChunk;
+
1126  int useLocalDataOnly = (pairRank == qureg.chunkId);
+
1127 
+
1128  if (useLocalDataOnly) {
+
1129  // swaps amplitudes locally, setting |a>=X|b>, and |b>=X|a>
+
1130  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
+
1131  } else {
+
1132  // swaps amplitudes with pair node
+
1133  exchangeStateVectors(qureg, pairRank);
+
1134  // modifies only |a>=X|b> (pair node handles the converse)
+ +
1136  qureg, ctrlMask, targMask,
+
1137  qureg.pairStateVec, // in
+
1138  qureg.stateVec); // out
+
1139  }
+
1140 }
-

References Qureg::chunkId, exchangeStateVectors(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_multiControlledMultiQubitNotDistributed(), and statevec_multiControlledMultiQubitNotLocal().

+

References Qureg::chunkId, exchangeStateVectors(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_multiControlledMultiQubitNotDistributed(), and statevec_multiControlledMultiQubitNotLocal().

@@ -3306,52 +3306,52 @@

Todo:
refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.
-

Definition at line 1503 of file QuEST_cpu_distributed.c.

-
1503  {
-
1504 
-
1505  // bit mask of target qubits (for quick collision checking)
-
1506  long long int targMask = getQubitBitMask(targs, numTargs);
-
1507 
-
1508  // find lowest qubit available for swapping (isn't in targs)
-
1509  int freeQb=0;
-
1510  while (maskContainsBit(targMask, freeQb))
-
1511  freeQb++;
-
1512 
-
1513  // assign indices of where each target will be swapped to (else itself)
-
1514  int swapTargs[numTargs];
-
1515  for (int t=0; t<numTargs; t++) {
-
1516  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
-
1517  swapTargs[t] = targs[t];
-
1518  else {
-
1519  // mark swap
-
1520  swapTargs[t] = freeQb;
-
1521 
-
1522  // update ctrlMask if swapped-out qubit was a control
-
1523  if (maskContainsBit(ctrlMask, swapTargs[t]))
-
1524  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
-
1525 
-
1526  // locate next available on-chunk qubit
-
1527  freeQb++;
-
1528  while (maskContainsBit(targMask, freeQb))
-
1529  freeQb++;
-
1530  }
-
1531  }
-
1532 
-
1533  // perform swaps as necessary
-
1534  for (int t=0; t<numTargs; t++)
-
1535  if (swapTargs[t] != targs[t])
-
1536  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1537 
-
1538  // all target qubits have now been swapped into local memory
-
1539  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
-
1540 
-
1541  // undo swaps
-
1542  for (int t=0; t<numTargs; t++)
-
1543  if (swapTargs[t] != targs[t])
-
1544  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1545 }
+

Definition at line 1514 of file QuEST_cpu_distributed.c.

+
1514  {
+
1515 
+
1516  // bit mask of target qubits (for quick collision checking)
+
1517  long long int targMask = getQubitBitMask(targs, numTargs);
+
1518 
+
1519  // find lowest qubit available for swapping (isn't in targs)
+
1520  int freeQb=0;
+
1521  while (maskContainsBit(targMask, freeQb))
+
1522  freeQb++;
+
1523 
+
1524  // assign indices of where each target will be swapped to (else itself)
+
1525  int swapTargs[numTargs];
+
1526  for (int t=0; t<numTargs; t++) {
+
1527  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
+
1528  swapTargs[t] = targs[t];
+
1529  else {
+
1530  // mark swap
+
1531  swapTargs[t] = freeQb;
+
1532 
+
1533  // update ctrlMask if swapped-out qubit was a control
+
1534  if (maskContainsBit(ctrlMask, swapTargs[t]))
+
1535  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
+
1536 
+
1537  // locate next available on-chunk qubit
+
1538  freeQb++;
+
1539  while (maskContainsBit(targMask, freeQb))
+
1540  freeQb++;
+
1541  }
+
1542  }
+
1543 
+
1544  // perform swaps as necessary
+
1545  for (int t=0; t<numTargs; t++)
+
1546  if (swapTargs[t] != targs[t])
+
1547  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
+
1548 
+
1549  // all target qubits have now been swapped into local memory
+
1550  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
+
1551 
+
1552  // undo swaps
+
1553  for (int t=0; t<numTargs; t++)
+
1554  if (swapTargs[t] != targs[t])
+
1555  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
+
1556 }
-

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

+

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

@@ -3405,56 +3405,56 @@

the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

-

Definition at line 1447 of file QuEST_cpu_distributed.c.

-
1447  {
-
1448  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
-
1449  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
-
1450 
-
1451  if (q1FitsInNode && q2FitsInNode) {
-
1452  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
1453 
-
1454  } else if (q1FitsInNode) {
-
1455  int qSwap = (q1 > 0)? q1-1 : q1+1;
-
1456 
-
1457  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1458  if (maskContainsBit(ctrlMask, qSwap))
-
1459  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
-
1460 
-
1461  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1462  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
-
1463  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1464 
-
1465  } else if (q2FitsInNode) {
-
1466  int qSwap = (q2 > 0)? q2-1 : q2+1;
-
1467 
+

Definition at line 1458 of file QuEST_cpu_distributed.c.

+
1458  {
+
1459  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
+
1460  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
+
1461 
+
1462  if (q1FitsInNode && q2FitsInNode) {
+
1463  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
+
1464 
+
1465  } else if (q1FitsInNode) {
+
1466  int qSwap = (q1 > 0)? q1-1 : q1+1;
+
1467 
1468  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
1469  if (maskContainsBit(ctrlMask, qSwap))
-
1470  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
-
1471 
-
1472  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1473  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
-
1474  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1475 
-
1476  } else {
-
1477  // we know with certainty that both q1 and q2 >= 2
-
1478  int swap1 = 0;
-
1479  int swap2 = 1;
-
1480 
-
1481  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
-
1482  if (maskContainsBit(ctrlMask, swap1))
-
1483  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
-
1484  if (maskContainsBit(ctrlMask, swap2))
-
1485  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
+
1470  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
+
1471 
+
1472  statevec_swapQubitAmps(qureg, q2, qSwap);
+
1473  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
+
1474  statevec_swapQubitAmps(qureg, q2, qSwap);
+
1475 
+
1476  } else if (q2FitsInNode) {
+
1477  int qSwap = (q2 > 0)? q2-1 : q2+1;
+
1478 
+
1479  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
+
1480  if (maskContainsBit(ctrlMask, qSwap))
+
1481  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
+
1482 
+
1483  statevec_swapQubitAmps(qureg, q1, qSwap);
+
1484  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
+
1485  statevec_swapQubitAmps(qureg, q1, qSwap);
1486 
-
1487  statevec_swapQubitAmps(qureg, q1, swap1);
-
1488  statevec_swapQubitAmps(qureg, q2, swap2);
-
1489  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
-
1490  statevec_swapQubitAmps(qureg, q1, swap1);
-
1491  statevec_swapQubitAmps(qureg, q2, swap2);
-
1492  }
-
1493 }
+
1487  } else {
+
1488  // we know with certainty that both q1 and q2 >= 2
+
1489  int swap1 = 0;
+
1490  int swap2 = 1;
+
1491 
+
1492  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
+
1493  if (maskContainsBit(ctrlMask, swap1))
+
1494  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
+
1495  if (maskContainsBit(ctrlMask, swap2))
+
1496  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
+
1497 
+
1498  statevec_swapQubitAmps(qureg, q1, swap1);
+
1499  statevec_swapQubitAmps(qureg, q2, swap2);
+
1500  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
+
1501  statevec_swapQubitAmps(qureg, q1, swap1);
+
1502  statevec_swapQubitAmps(qureg, q2, swap2);
+
1503  }
+
1504 }
-

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

+

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

@@ -3502,45 +3502,45 @@

-

Definition at line 1007 of file QuEST_cpu_distributed.c.

-
1008 {
-
1009  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1010  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1011  Complex rot1, rot2;
-
1012 
-
1013  // rank's chunk is in upper half of block
-
1014  int rankIsUpper;
-
1015  int pairRank; // rank of corresponding chunk
+

Definition at line 1011 of file QuEST_cpu_distributed.c.

+
1012 {
+
1013  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1014  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1015  Complex rot1, rot2;
1016 
-
1017  if (useLocalDataOnly){
-
1018  // all values required to update state vector lie in this rank
-
1019  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
1020  } else {
-
1021  // need to get corresponding chunk of state vector from other rank
-
1022  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1023  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
1024  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1025 
-
1026  // get corresponding values from my pair
-
1027  exchangeStateVectors(qureg, pairRank);
-
1028 
-
1029  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
-
1030  // in the correct order
-
1031  if (rankIsUpper){
-
1032  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1033  qureg.stateVec, //upper
-
1034  qureg.pairStateVec, //lower
-
1035  qureg.stateVec); //output
-
1036  } else {
-
1037  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1038  qureg.pairStateVec, //upper
-
1039  qureg.stateVec, //lower
-
1040  qureg.stateVec); //output
-
1041  }
-
1042  }
-
1043 }
+
1017  // rank's chunk is in upper half of block
+
1018  int rankIsUpper;
+
1019  int pairRank; // rank of corresponding chunk
+
1020 
+
1021  if (useLocalDataOnly){
+
1022  // all values required to update state vector lie in this rank
+
1023  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
+
1024  } else {
+
1025  // need to get corresponding chunk of state vector from other rank
+
1026  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1027  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
1028  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1029 
+
1030  // get corresponding values from my pair
+
1031  exchangeStateVectors(qureg, pairRank);
+
1032 
+
1033  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
+
1034  // in the correct order
+
1035  if (rankIsUpper){
+
1036  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
+
1037  qureg.stateVec, //upper
+
1038  qureg.pairStateVec, //lower
+
1039  qureg.stateVec); //output
+
1040  } else {
+
1041  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
+
1042  qureg.pairStateVec, //upper
+
1043  qureg.stateVec, //lower
+
1044  qureg.stateVec); //output
+
1045  }
+
1046  }
+
1047 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

@@ -3570,34 +3570,34 @@

-

Definition at line 1044 of file QuEST_cpu_distributed.c.

-
1045 {
-
1046  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1047  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1048 
-
1049  // rank's chunk is in upper half of block
-
1050  int rankIsUpper;
-
1051  int pairRank; // rank of corresponding chunk
+

Definition at line 1048 of file QuEST_cpu_distributed.c.

+
1049 {
+
1050  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1051  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1052 
-
1053  if (useLocalDataOnly){
-
1054  // all values required to update state vector lie in this rank
-
1055  statevec_pauliXLocal(qureg, targetQubit);
-
1056  } else {
-
1057  // need to get corresponding chunk of state vector from other rank
-
1058  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1059  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1060  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1061  // get corresponding values from my pair
-
1062  exchangeStateVectors(qureg, pairRank);
-
1063  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
-
1064  // this rank's values with pair values
- -
1066  qureg.pairStateVec, // in
-
1067  qureg.stateVec); // out
-
1068  }
-
1069 }
+
1053  // rank's chunk is in upper half of block
+
1054  int rankIsUpper;
+
1055  int pairRank; // rank of corresponding chunk
+
1056 
+
1057  if (useLocalDataOnly){
+
1058  // all values required to update state vector lie in this rank
+
1059  statevec_pauliXLocal(qureg, targetQubit);
+
1060  } else {
+
1061  // need to get corresponding chunk of state vector from other rank
+
1062  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1063  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1064  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
1065  // get corresponding values from my pair
+
1066  exchangeStateVectors(qureg, pairRank);
+
1067  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
+
1068  // this rank's values with pair values
+ +
1070  qureg.pairStateVec, // in
+
1071  qureg.stateVec); // out
+
1072  }
+
1073 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliXDistributed(), and statevec_pauliXLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliXDistributed(), and statevec_pauliXLocal().

@@ -3627,32 +3627,32 @@

-

Definition at line 1138 of file QuEST_cpu_distributed.c.

-
1139 {
-
1140  int conjFac = 1;
-
1141 
-
1142  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1143  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1144  int rankIsUpper; // rank's chunk is in upper half of block
-
1145  int pairRank; // rank of corresponding chunk
-
1146 
-
1147  if (useLocalDataOnly){
-
1148  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1149  } else {
-
1150  // need to get corresponding chunk of state vector from other rank
-
1151  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1152  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1153  // get corresponding values from my pair
-
1154  exchangeStateVectors(qureg, pairRank);
-
1155  // this rank's values are either in the upper of lower half of the block
- -
1157  qureg.pairStateVec, // in
-
1158  qureg.stateVec, // out
-
1159  rankIsUpper, conjFac);
-
1160  }
-
1161 }
+

Definition at line 1142 of file QuEST_cpu_distributed.c.

+
1143 {
+
1144  int conjFac = 1;
+
1145 
+
1146  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1147  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1148  int rankIsUpper; // rank's chunk is in upper half of block
+
1149  int pairRank; // rank of corresponding chunk
+
1150 
+
1151  if (useLocalDataOnly){
+
1152  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
1153  } else {
+
1154  // need to get corresponding chunk of state vector from other rank
+
1155  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1156  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1157  // get corresponding values from my pair
+
1158  exchangeStateVectors(qureg, pairRank);
+
1159  // this rank's values are either in the upper of lower half of the block
+ +
1161  qureg.pairStateVec, // in
+
1162  qureg.stateVec, // out
+
1163  rankIsUpper, conjFac);
+
1164  }
+
1165 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

@@ -3682,32 +3682,32 @@

-

Definition at line 1163 of file QuEST_cpu_distributed.c.

-
1164 {
-
1165  int conjFac = -1;
-
1166 
-
1167  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1168  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1169  int rankIsUpper; // rank's chunk is in upper half of block
-
1170  int pairRank; // rank of corresponding chunk
-
1171 
-
1172  if (useLocalDataOnly){
-
1173  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1174  } else {
-
1175  // need to get corresponding chunk of state vector from other rank
-
1176  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1177  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1178  // get corresponding values from my pair
-
1179  exchangeStateVectors(qureg, pairRank);
-
1180  // this rank's values are either in the upper of lower half of the block
- -
1182  qureg.pairStateVec, // in
-
1183  qureg.stateVec, // out
-
1184  rankIsUpper, conjFac);
-
1185  }
-
1186 }
+

Definition at line 1167 of file QuEST_cpu_distributed.c.

+
1168 {
+
1169  int conjFac = -1;
+
1170 
+
1171  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1172  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1173  int rankIsUpper; // rank's chunk is in upper half of block
+
1174  int pairRank; // rank of corresponding chunk
+
1175 
+
1176  if (useLocalDataOnly){
+
1177  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
1178  } else {
+
1179  // need to get corresponding chunk of state vector from other rank
+
1180  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1181  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1182  // get corresponding values from my pair
+
1183  exchangeStateVectors(qureg, pairRank);
+
1184  // this rank's values are either in the upper of lower half of the block
+ +
1186  qureg.pairStateVec, // in
+
1187  qureg.stateVec, // out
+
1188  rankIsUpper, conjFac);
+
1189  }
+
1190 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

@@ -3743,28 +3743,28 @@

-

Definition at line 1420 of file QuEST_cpu_distributed.c.

-
1420  {
-
1421 
-
1422  // perform locally if possible
-
1423  int qbBig = (qb1 > qb2)? qb1 : qb2;
-
1424  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
-
1425  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
1426 
-
1427  // do nothing if this node contains no amplitudes to swap
-
1428  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
-
1429  if (oddParityGlobalInd == -1)
-
1430  return;
-
1431 
-
1432  // determine and swap amps with pair node
-
1433  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
-
1434  exchangeStateVectors(qureg, pairRank);
-
1435  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
-
1436 }
+

Definition at line 1431 of file QuEST_cpu_distributed.c.

+
1431  {
+
1432 
+
1433  // perform locally if possible
+
1434  int qbBig = (qb1 > qb2)? qb1 : qb2;
+
1435  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
+
1436  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
+
1437 
+
1438  // do nothing if this node contains no amplitudes to swap
+
1439  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
+
1440  if (oddParityGlobalInd == -1)
+
1441  return;
+
1442 
+
1443  // determine and swap amps with pair node
+
1444  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
+
1445  exchangeStateVectors(qureg, pairRank);
+
1446  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
+
1447 }
-

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

+

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

-

Referenced by statevec_multiControlledMultiQubitUnitary(), and statevec_multiControlledTwoQubitUnitary().

+

Referenced by statevec_multiControlledMultiQubitUnitary(), and statevec_multiControlledTwoQubitUnitary().

@@ -3800,140 +3800,140 @@

-

Definition at line 891 of file QuEST_cpu_distributed.c.

-
892 {
-
893  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
894  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
895  Complex rot1, rot2;
-
896 
-
897  // rank's chunk is in upper half of block
-
898  int rankIsUpper;
-
899  int pairRank; // rank of corresponding chunk
+

Definition at line 895 of file QuEST_cpu_distributed.c.

+
896 {
+
897  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
898  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
899  Complex rot1, rot2;
900 
-
901  if (useLocalDataOnly){
-
902  // all values required to update state vector lie in this rank
-
903  statevec_unitaryLocal(qureg, targetQubit, u);
-
904  } else {
-
905  // need to get corresponding chunk of state vector from other rank
-
906  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
907  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
908  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
909  // get corresponding values from my pair
-
910  exchangeStateVectors(qureg, pairRank);
-
911 
-
912  // this rank's values are either in the upper of lower half of the block.
-
913  // send values to compactUnitaryDistributed in the correct order
-
914  if (rankIsUpper){
-
915  statevec_unitaryDistributed(qureg,rot1,rot2,
-
916  qureg.stateVec, //upper
-
917  qureg.pairStateVec, //lower
-
918  qureg.stateVec); //output
-
919  } else {
-
920  statevec_unitaryDistributed(qureg,rot1,rot2,
-
921  qureg.pairStateVec, //upper
-
922  qureg.stateVec, //lower
-
923  qureg.stateVec); //output
-
924  }
-
925  }
-
926 
-
927 
-
928 }
+
901  // rank's chunk is in upper half of block
+
902  int rankIsUpper;
+
903  int pairRank; // rank of corresponding chunk
+
904 
+
905  if (useLocalDataOnly){
+
906  // all values required to update state vector lie in this rank
+
907  statevec_unitaryLocal(qureg, targetQubit, u);
+
908  } else {
+
909  // need to get corresponding chunk of state vector from other rank
+
910  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
911  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
912  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
913  // get corresponding values from my pair
+
914  exchangeStateVectors(qureg, pairRank);
+
915 
+
916  // this rank's values are either in the upper of lower half of the block.
+
917  // send values to compactUnitaryDistributed in the correct order
+
918  if (rankIsUpper){
+
919  statevec_unitaryDistributed(qureg,rot1,rot2,
+
920  qureg.stateVec, //upper
+
921  qureg.pairStateVec, //lower
+
922  qureg.stateVec); //output
+
923  } else {
+
924  statevec_unitaryDistributed(qureg,rot1,rot2,
+
925  qureg.pairStateVec, //upper
+
926  qureg.stateVec, //lower
+
927  qureg.stateVec); //output
+
928  }
+
929  }
+
930 
+
931 
+
932 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
-
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
-
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
+
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
+
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3474
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
+
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3513
+
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:230
+
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:638
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2503
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2437
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2612
-
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
+
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2542
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2476
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
+
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2651
+
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
+
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
#define qreal
-
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
-
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
+
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
+
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3847
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
+
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3887
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
qreal imag[2][2]
Definition: QuEST.h:140
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
+
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2943
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2056
-
void exchangeStateVectors(Qureg qureg, int pairRank)
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
+
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2095
+
void exchangeStateVectors(Qureg qureg, int pairRank)
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2906
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
+
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2945
+
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:306
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
static int getChunkIdFromIndex(Qureg qureg, long long int index)
-
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2795
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2112
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2375
-
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
+
static int getChunkIdFromIndex(Qureg qureg, long long int index)
+
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2834
+
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2151
+
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2414
+
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
qreal real[2][2]
Definition: QuEST.h:139
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3809
-
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3849
+
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
-
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2703
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
+
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
+
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:494
+
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
+
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2742
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3925
+
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3965
qreal imag
Definition: QuEST.h:106
-
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
-
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
+
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
+
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:547
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
+
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3100
+
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3139
static int maskContainsBit(const long long int mask, const int bitInd)
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2997
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
-
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
+
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:3036
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
+
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
diff --git a/docs/QuEST__cpu__distributed_8c_source.html b/docs/QuEST__cpu__distributed_8c_source.html index 07ef751fa..d09a7e428 100644 --- a/docs/QuEST__cpu__distributed_8c_source.html +++ b/docs/QuEST__cpu__distributed_8c_source.html @@ -27,7 +27,7 @@ @@ -205,1538 +205,1551 @@
154 
155  validateNumRanks(env.numRanks, __func__);
156 
- -
158 
-
159  return env;
-
160 }
-
161 
- -
163  MPI_Barrier(MPI_COMM_WORLD);
-
164 }
-
165 
-
166 int syncQuESTSuccess(int successCode){
-
167  int totalSuccess;
-
168  MPI_Allreduce(&successCode, &totalSuccess, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
-
169  return totalSuccess;
-
170 }
-
171 
- -
173  int finalized;
-
174  MPI_Finalized(&finalized);
-
175  if (!finalized) MPI_Finalize();
-
176  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
-
177 }
-
178 
- -
180  if (env.rank==0){
-
181  printf("EXECUTION ENVIRONMENT:\n");
-
182  printf("Running distributed (MPI) version\n");
-
183  printf("Number of ranks is %d\n", env.numRanks);
-
184 # ifdef _OPENMP
-
185  printf("OpenMP enabled\n");
-
186  printf("Number of threads available is %d\n", omp_get_max_threads());
-
187 # else
-
188  printf("OpenMP disabled\n");
-
189 # endif
-
190  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal) );
-
191  }
-
192 }
-
193 
-
194 void getEnvironmentString(QuESTEnv env, char str[200]){
-
195  int ompStatus=0;
-
196  int numThreads=1;
-
197 # ifdef _OPENMP
-
198  ompStatus=1;
-
199  numThreads=omp_get_max_threads();
-
200 # endif
-
201  sprintf(str, "CUDA=0 OpenMP=%d MPI=1 threads=%d ranks=%d", ompStatus, numThreads, env.numRanks);
-
202 }
-
203 
-
204 int getChunkIdFromIndex(Qureg qureg, long long int index){
-
205  return index/qureg.numAmpsPerChunk; // this is numAmpsPerChunk
+
157  env.seeds = NULL;
+
158  env.numSeeds = 0;
+
159  seedQuESTDefault(&env);
+
160 
+
161  return env;
+
162 }
+
163 
+ +
165  MPI_Barrier(MPI_COMM_WORLD);
+
166 }
+
167 
+
168 int syncQuESTSuccess(int successCode){
+
169  int totalSuccess;
+
170  MPI_Allreduce(&successCode, &totalSuccess, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
+
171  return totalSuccess;
+
172 }
+
173 
+ +
175  free(env.seeds);
+
176 
+
177  int finalized;
+
178  MPI_Finalized(&finalized);
+
179  if (!finalized) MPI_Finalize();
+
180  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
+
181 }
+
182 
+ +
184  if (env.rank==0){
+
185  printf("EXECUTION ENVIRONMENT:\n");
+
186  printf("Running distributed (MPI) version\n");
+
187  printf("Number of ranks is %d\n", env.numRanks);
+
188 # ifdef _OPENMP
+
189  printf("OpenMP enabled\n");
+
190  printf("Number of threads available is %d\n", omp_get_max_threads());
+
191 # else
+
192  printf("OpenMP disabled\n");
+
193 # endif
+
194  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal) );
+
195  }
+
196 }
+
197 
+
198 void getEnvironmentString(QuESTEnv env, char str[200]){
+
199  int ompStatus=0;
+
200  int numThreads=1;
+
201 # ifdef _OPENMP
+
202  ompStatus=1;
+
203  numThreads=omp_get_max_threads();
+
204 # endif
+
205  sprintf(str, "CUDA=0 OpenMP=%d MPI=1 threads=%d ranks=%d", ompStatus, numThreads, env.numRanks);
206 }
207 
-
208 qreal statevec_getRealAmp(Qureg qureg, long long int index){
-
209  int chunkId = getChunkIdFromIndex(qureg, index);
-
210  qreal el;
-
211  if (qureg.chunkId==chunkId){
-
212  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
-
213  }
-
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
215  return el;
-
216 }
-
217 
-
218 qreal statevec_getImagAmp(Qureg qureg, long long int index){
-
219  int chunkId = getChunkIdFromIndex(qureg, index);
-
220  qreal el;
-
221  if (qureg.chunkId==chunkId){
-
222  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
-
223  }
-
224  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
225  return el;
-
226 }
-
227 
-
236 static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
-
238 {
-
239  long long int sizeHalfBlock = 1LL << (targetQubit);
-
240  long long int sizeBlock = sizeHalfBlock*2;
-
241  long long int posInBlock = (chunkId*chunkSize) % sizeBlock;
-
242  return posInBlock<sizeHalfBlock;
-
243 }
-
244 
-
246 static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
247 {
-
248  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
249  long long int sizeOuterBlock = sizeOuterHalfBlock*2;
-
250  long long int posInBlock = (chunkId*chunkSize) % sizeOuterBlock;
-
251  return posInBlock<sizeOuterHalfBlock;
-
252 }
-
253 
-
268 static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
-
269 {
-
270  if (chunkIsUpper){
-
271  *rot1=alpha;
-
272  rot2->real=-beta.real;
-
273  rot2->imag=-beta.imag;
-
274  } else {
-
275  *rot1=beta;
-
276  *rot2=alpha;
-
277  }
-
278 }
-
279 
- -
294 {
-
295  if (chunkIsUpper){
-
296  *rot1=(Complex) {.real=u.real[0][0], .imag=u.imag[0][0]};
-
297  *rot2=(Complex) {.real=u.real[0][1], .imag=u.imag[0][1]};
-
298  } else {
-
299  *rot1=(Complex) {.real=u.real[1][0], .imag=u.imag[1][0]};
-
300  *rot2=(Complex) {.real=u.real[1][1], .imag=u.imag[1][1]};
-
301  }
-
302 }
-
303 
-
313 static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
-
314 {
-
315  long long int sizeHalfBlock = 1LL << (targetQubit);
-
316  int chunksPerHalfBlock = sizeHalfBlock/chunkSize;
-
317  if (chunkIsUpper){
-
318  return chunkId + chunksPerHalfBlock;
-
319  } else {
-
320  return chunkId - chunksPerHalfBlock;
-
321  }
-
322 }
-
323 
-
324 static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
325 {
-
326  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
327  int chunksPerOuterHalfBlock = sizeOuterHalfBlock/chunkSize;
-
328  if (chunkIsUpper){
-
329  return chunkId + chunksPerOuterHalfBlock;
-
330  } else {
-
331  return chunkId - chunksPerOuterHalfBlock;
-
332  }
-
333 }
-
334 
-
335 static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId,
-
336  long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
337 {
-
338  long long int sizeOuterHalfBlockBiggerQubit = 1LL << (biggerQubit+numQubits);
-
339  long long int sizeOuterHalfBlockSmallerQubit = 1LL << (smallerQubit+numQubits);
-
340  int chunksPerOuterHalfBlockSmallerQubit = sizeOuterHalfBlockSmallerQubit/chunkSize;
-
341  int chunksPerOuterHalfBlockBiggerQubit = sizeOuterHalfBlockBiggerQubit/chunkSize;
-
342  int rank;
-
343  if (chunkIsUpperBiggerQubit){
-
344  rank = chunkId + chunksPerOuterHalfBlockBiggerQubit;
-
345  } else {
-
346  rank = chunkId - chunksPerOuterHalfBlockBiggerQubit;
-
347  }
-
348 
-
349  if (chunkIsUpperSmallerQubit){
-
350  rank = rank + chunksPerOuterHalfBlockSmallerQubit;
-
351  } else {
-
352  rank = rank - chunksPerOuterHalfBlockSmallerQubit;
-
353  }
-
354 
-
355  return rank;
-
356 }
-
357 
-
365 static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
-
367 {
-
368  long long int sizeHalfBlock = 1LL << (targetQubit);
-
369  if (chunkSize > sizeHalfBlock) return 1;
-
370  else return 0;
-
371 }
-
372 
-
373 static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit) {
-
374  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
-
375  if (chunkSize > sizeOuterHalfBlock) return 1;
-
376  else return 0;
-
377 }
-
378 
- -
382 
-
383  // Remember that for every amplitude that `vec` stores on the node,
-
384  // `matr` stores an entire column. Ergo there are always an integer
-
385  // number (in fact, a power of 2) number of `matr`s columns on each node.
-
386  // Since the total size of `vec` (between all nodes) is one column
-
387  // and each node stores (possibly) multiple columns (vec.numAmpsPerChunk as many),
-
388  // `vec` can be fit entirely inside a single node's matr.pairStateVec (with excess!)
-
389 
-
390  // copy this node's vec segment into this node's matr pairState (in the right spot)
-
391  long long int numLocalAmps = vec.numAmpsPerChunk;
-
392  long long int myOffset = vec.chunkId * numLocalAmps;
-
393  memcpy(&matr.pairStateVec.real[myOffset], vec.stateVec.real, numLocalAmps * sizeof(qreal));
-
394  memcpy(&matr.pairStateVec.imag[myOffset], vec.stateVec.imag, numLocalAmps * sizeof(qreal));
-
395 
-
396  // we now want to share this node's vec segment with other node, so that
-
397  // vec is cloned in every node's matr.pairStateVec
-
398 
-
399  // work out how many messages needed to send vec chunks (2GB limit)
-
400  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
401  if (numLocalAmps < maxMsgSize)
-
402  maxMsgSize = numLocalAmps;
-
403  // safely assume MPI_MAX... = 2^n, so division always exact:
-
404  int numMsgs = numLocalAmps / maxMsgSize;
-
405 
-
406  // every node gets a turn at being the broadcaster
-
407  for (int broadcaster=0; broadcaster < vec.numChunks; broadcaster++) {
-
408 
-
409  long long int otherOffset = broadcaster * numLocalAmps;
-
410 
-
411  // every node sends a slice of qureg's pairState to every other
-
412  for (int i=0; i< numMsgs; i++) {
-
413 
-
414  // by sending that slice in further slices (due to bandwidth limit)
-
415  MPI_Bcast(
-
416  &matr.pairStateVec.real[otherOffset + i*maxMsgSize],
-
417  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
418  MPI_Bcast(
-
419  &matr.pairStateVec.imag[otherOffset + i*maxMsgSize],
-
420  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
421  }
-
422  }
-
423 }
-
424 
- -
426 
-
427  // set qureg's pairState is to be the full pureState (on every node)
-
428  copyVecIntoMatrixPairState(qureg, pureState);
-
429 
-
430  // collect calcFidelityLocal by every machine
-
431  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
-
432 
-
433  // sum each localSum
-
434  qreal globalSum;
-
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
208 int getChunkIdFromIndex(Qureg qureg, long long int index){
+
209  return index/qureg.numAmpsPerChunk; // this is numAmpsPerChunk
+
210 }
+
211 
+
212 qreal statevec_getRealAmp(Qureg qureg, long long int index){
+
213  int chunkId = getChunkIdFromIndex(qureg, index);
+
214  qreal el;
+
215  if (qureg.chunkId==chunkId){
+
216  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
+
217  }
+
218  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
+
219  return el;
+
220 }
+
221 
+
222 qreal statevec_getImagAmp(Qureg qureg, long long int index){
+
223  int chunkId = getChunkIdFromIndex(qureg, index);
+
224  qreal el;
+
225  if (qureg.chunkId==chunkId){
+
226  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
+
227  }
+
228  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
+
229  return el;
+
230 }
+
231 
+
240 static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
+
242 {
+
243  long long int sizeHalfBlock = 1LL << (targetQubit);
+
244  long long int sizeBlock = sizeHalfBlock*2;
+
245  long long int posInBlock = (chunkId*chunkSize) % sizeBlock;
+
246  return posInBlock<sizeHalfBlock;
+
247 }
+
248 
+
250 static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
+
251 {
+
252  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
+
253  long long int sizeOuterBlock = sizeOuterHalfBlock*2;
+
254  long long int posInBlock = (chunkId*chunkSize) % sizeOuterBlock;
+
255  return posInBlock<sizeOuterHalfBlock;
+
256 }
+
257 
+
272 static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
+
273 {
+
274  if (chunkIsUpper){
+
275  *rot1=alpha;
+
276  rot2->real=-beta.real;
+
277  rot2->imag=-beta.imag;
+
278  } else {
+
279  *rot1=beta;
+
280  *rot2=alpha;
+
281  }
+
282 }
+
283 
+ +
298 {
+
299  if (chunkIsUpper){
+
300  *rot1=(Complex) {.real=u.real[0][0], .imag=u.imag[0][0]};
+
301  *rot2=(Complex) {.real=u.real[0][1], .imag=u.imag[0][1]};
+
302  } else {
+
303  *rot1=(Complex) {.real=u.real[1][0], .imag=u.imag[1][0]};
+
304  *rot2=(Complex) {.real=u.real[1][1], .imag=u.imag[1][1]};
+
305  }
+
306 }
+
307 
+
317 static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
+
318 {
+
319  long long int sizeHalfBlock = 1LL << (targetQubit);
+
320  int chunksPerHalfBlock = sizeHalfBlock/chunkSize;
+
321  if (chunkIsUpper){
+
322  return chunkId + chunksPerHalfBlock;
+
323  } else {
+
324  return chunkId - chunksPerHalfBlock;
+
325  }
+
326 }
+
327 
+
328 static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
+
329 {
+
330  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
+
331  int chunksPerOuterHalfBlock = sizeOuterHalfBlock/chunkSize;
+
332  if (chunkIsUpper){
+
333  return chunkId + chunksPerOuterHalfBlock;
+
334  } else {
+
335  return chunkId - chunksPerOuterHalfBlock;
+
336  }
+
337 }
+
338 
+
339 static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId,
+
340  long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
+
341 {
+
342  long long int sizeOuterHalfBlockBiggerQubit = 1LL << (biggerQubit+numQubits);
+
343  long long int sizeOuterHalfBlockSmallerQubit = 1LL << (smallerQubit+numQubits);
+
344  int chunksPerOuterHalfBlockSmallerQubit = sizeOuterHalfBlockSmallerQubit/chunkSize;
+
345  int chunksPerOuterHalfBlockBiggerQubit = sizeOuterHalfBlockBiggerQubit/chunkSize;
+
346  int rank;
+
347  if (chunkIsUpperBiggerQubit){
+
348  rank = chunkId + chunksPerOuterHalfBlockBiggerQubit;
+
349  } else {
+
350  rank = chunkId - chunksPerOuterHalfBlockBiggerQubit;
+
351  }
+
352 
+
353  if (chunkIsUpperSmallerQubit){
+
354  rank = rank + chunksPerOuterHalfBlockSmallerQubit;
+
355  } else {
+
356  rank = rank - chunksPerOuterHalfBlockSmallerQubit;
+
357  }
+
358 
+
359  return rank;
+
360 }
+
361 
+
369 static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
+
371 {
+
372  long long int sizeHalfBlock = 1LL << (targetQubit);
+
373  if (chunkSize > sizeHalfBlock) return 1;
+
374  else return 0;
+
375 }
+
376 
+
377 static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit) {
+
378  long long int sizeOuterHalfBlock = 1LL << (targetQubit+numQubits);
+
379  if (chunkSize > sizeOuterHalfBlock) return 1;
+
380  else return 0;
+
381 }
+
382 
+ +
386 
+
387  // Remember that for every amplitude that `vec` stores on the node,
+
388  // `matr` stores an entire column. Ergo there are always an integer
+
389  // number (in fact, a power of 2) number of `matr`s columns on each node.
+
390  // Since the total size of `vec` (between all nodes) is one column
+
391  // and each node stores (possibly) multiple columns (vec.numAmpsPerChunk as many),
+
392  // `vec` can be fit entirely inside a single node's matr.pairStateVec (with excess!)
+
393 
+
394  // copy this node's vec segment into this node's matr pairState (in the right spot)
+
395  long long int numLocalAmps = vec.numAmpsPerChunk;
+
396  long long int myOffset = vec.chunkId * numLocalAmps;
+
397  memcpy(&matr.pairStateVec.real[myOffset], vec.stateVec.real, numLocalAmps * sizeof(qreal));
+
398  memcpy(&matr.pairStateVec.imag[myOffset], vec.stateVec.imag, numLocalAmps * sizeof(qreal));
+
399 
+
400  // we now want to share this node's vec segment with other node, so that
+
401  // vec is cloned in every node's matr.pairStateVec
+
402 
+
403  // work out how many messages needed to send vec chunks (2GB limit)
+
404  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
+
405  if (numLocalAmps < maxMsgSize)
+
406  maxMsgSize = numLocalAmps;
+
407  // safely assume MPI_MAX... = 2^n, so division always exact:
+
408  int numMsgs = numLocalAmps / maxMsgSize;
+
409 
+
410  // every node gets a turn at being the broadcaster
+
411  for (int broadcaster=0; broadcaster < vec.numChunks; broadcaster++) {
+
412 
+
413  long long int otherOffset = broadcaster * numLocalAmps;
+
414 
+
415  // every node sends a slice of qureg's pairState to every other
+
416  for (int i=0; i< numMsgs; i++) {
+
417 
+
418  // by sending that slice in further slices (due to bandwidth limit)
+
419  MPI_Bcast(
+
420  &matr.pairStateVec.real[otherOffset + i*maxMsgSize],
+
421  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
422  MPI_Bcast(
+
423  &matr.pairStateVec.imag[otherOffset + i*maxMsgSize],
+
424  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
425  }
+
426  }
+
427 }
+
428 
+ +
430 
+
431  // set qureg's pairState is to be the full pureState (on every node)
+
432  copyVecIntoMatrixPairState(qureg, pureState);
+
433 
+
434  // collect calcFidelityLocal by every machine
+
435  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
436 
-
437  return globalSum;
-
438 }
-
439 
- -
441 
- -
443 
-
444  qreal globalSum;
-
445  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
446 
-
447  qreal dist = sqrt(globalSum);
-
448  return dist;
-
449 }
-
450 
- -
452 
-
453  qreal localSum = densmatr_calcInnerProductLocal(a, b);
-
454 
-
455  qreal globalSum;
-
456  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
457 
-
458  qreal dist = globalSum;
-
459  return dist;
-
460 }
-
461 
-
462 void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg) {
-
463 
-
464  if (targetQureg.numChunks==1){
-
465  // local version
-
466  // save pointers to qureg's pair state
-
467  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
-
468  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
-
469 
-
470  // populate qureg pair state with pure state (by repointing)
-
471  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
-
472  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
+
437  // sum each localSum
+
438  qreal globalSum;
+
439  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
440 
+
441  return globalSum;
+
442 }
+
443 
+ +
445 
+ +
447 
+
448  qreal globalSum;
+
449  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
450 
+
451  qreal dist = sqrt(globalSum);
+
452  return dist;
+
453 }
+
454 
+ +
456 
+
457  qreal localSum = densmatr_calcInnerProductLocal(a, b);
+
458 
+
459  qreal globalSum;
+
460  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
461 
+
462  qreal dist = globalSum;
+
463  return dist;
+
464 }
+
465 
+
466 void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg) {
+
467 
+
468  if (targetQureg.numChunks==1){
+
469  // local version
+
470  // save pointers to qureg's pair state
+
471  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
+
472  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
473 
-
474  // populate density matrix via it's pairState
-
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
476 
-
477  // restore pointers
-
478  targetQureg.pairStateVec.real = quregPairRePtr;
-
479  targetQureg.pairStateVec.imag = quregPairImPtr;
-
480  } else {
-
481  // set qureg's pairState is to be the full pure state (on every node)
-
482  copyVecIntoMatrixPairState(targetQureg, copyQureg);
-
483 
-
484  // update every density matrix chunk using pairState
-
485  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
486  }
-
487 }
-
488 
-
489 void exchangeStateVectors(Qureg qureg, int pairRank){
-
490  // MPI send/receive vars
-
491  int TAG=100;
-
492  MPI_Status status;
-
493 
-
494  // Multiple messages are required as MPI uses int rather than long long int for count
-
495  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
496  // to be safe
-
497  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
498  if (qureg.numAmpsPerChunk < maxMessageCount)
-
499  maxMessageCount = qureg.numAmpsPerChunk;
-
500 
-
501  // safely assume MPI_MAX... = 2^n, so division always exact
-
502  int numMessages = qureg.numAmpsPerChunk/maxMessageCount;
-
503  int i;
-
504  long long int offset;
-
505  // send my state vector to pairRank's qureg.pairStateVec
-
506  // receive pairRank's state vector into qureg.pairStateVec
-
507  for (i=0; i<numMessages; i++){
-
508  offset = i*maxMessageCount;
-
509  MPI_Sendrecv(&qureg.stateVec.real[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
510  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
511  pairRank, TAG, MPI_COMM_WORLD, &status);
-
512  //printf("rank: %d err: %d\n", qureg.rank, err);
-
513  MPI_Sendrecv(&qureg.stateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
-
514  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
+
474  // populate qureg pair state with pure state (by repointing)
+
475  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
+
476  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
+
477 
+
478  // populate density matrix via it's pairState
+
479  densmatr_initPureStateLocal(targetQureg, copyQureg);
+
480 
+
481  // restore pointers
+
482  targetQureg.pairStateVec.real = quregPairRePtr;
+
483  targetQureg.pairStateVec.imag = quregPairImPtr;
+
484  } else {
+
485  // set qureg's pairState is to be the full pure state (on every node)
+
486  copyVecIntoMatrixPairState(targetQureg, copyQureg);
+
487 
+
488  // update every density matrix chunk using pairState
+
489  densmatr_initPureStateLocal(targetQureg, copyQureg);
+
490  }
+
491 }
+
492 
+
493 void exchangeStateVectors(Qureg qureg, int pairRank){
+
494  // MPI send/receive vars
+
495  int TAG=100;
+
496  MPI_Status status;
+
497 
+
498  // Multiple messages are required as MPI uses int rather than long long int for count
+
499  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
+
500  // to be safe
+
501  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
+
502  if (qureg.numAmpsPerChunk < maxMessageCount)
+
503  maxMessageCount = qureg.numAmpsPerChunk;
+
504 
+
505  // safely assume MPI_MAX... = 2^n, so division always exact
+
506  int numMessages = qureg.numAmpsPerChunk/maxMessageCount;
+
507  int i;
+
508  long long int offset;
+
509  // send my state vector to pairRank's qureg.pairStateVec
+
510  // receive pairRank's state vector into qureg.pairStateVec
+
511  for (i=0; i<numMessages; i++){
+
512  offset = i*maxMessageCount;
+
513  MPI_Sendrecv(&qureg.stateVec.real[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
+
514  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
515  pairRank, TAG, MPI_COMM_WORLD, &status);
-
516  }
-
517 }
-
518 
-
519 void exchangePairStateVectorHalves(Qureg qureg, int pairRank){
-
520  // MPI send/receive vars
-
521  int TAG=100;
-
522  MPI_Status status;
-
523  long long int numAmpsToSend = qureg.numAmpsPerChunk >> 1;
-
524 
-
525  // Multiple messages are required as MPI uses int rather than long long int for count
-
526  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
-
527  // to be safe
-
528  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
-
529  if (numAmpsToSend < maxMessageCount)
-
530  maxMessageCount = numAmpsToSend;
-
531 
-
532  // safely assume MPI_MAX... = 2^n, so division always exact
-
533  int numMessages = numAmpsToSend/maxMessageCount;
-
534  int i;
-
535  long long int offset;
-
536  // send the bottom half of my state vector to the top half of pairRank's qureg.pairStateVec
-
537  // receive pairRank's state vector into the top of qureg.pairStateVec
-
538  for (i=0; i<numMessages; i++){
-
539  offset = i*maxMessageCount;
-
540  MPI_Sendrecv(&qureg.pairStateVec.real[offset+numAmpsToSend], maxMessageCount,
-
541  MPI_QuEST_REAL, pairRank, TAG,
-
542  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
-
543  pairRank, TAG, MPI_COMM_WORLD, &status);
-
544  //printf("rank: %d err: %d\n", qureg.rank, err);
-
545  MPI_Sendrecv(&qureg.pairStateVec.imag[offset+numAmpsToSend], maxMessageCount,
-
546  MPI_QuEST_REAL, pairRank, TAG,
-
547  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
-
548  pairRank, TAG, MPI_COMM_WORLD, &status);
-
549  }
-
550 }
-
551 
-
552 // @todo decide where this function should go. It is a preparation for MPI data transfer function
- -
554  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
555  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
556  long long int thisInnerBlock, // current block
-
557  thisOuterColumn, // current column in density matrix
-
558  thisIndex, // current index in (density matrix representation) state vector
-
559  thisIndexInOuterColumn,
-
560  thisIndexInInnerBlock;
-
561 
-
562  int outerBit;
-
563 
-
564  long long int thisTask;
-
565  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
566 
-
567  // set dimensions
-
568  sizeInnerHalfBlock = 1LL << targetQubit;
-
569  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
570  sizeOuterHalfColumn = 1LL << qureg.numQubitsRepresented;
-
571  sizeOuterColumn = 2LL * sizeOuterHalfColumn;
-
572 
-
573 # ifdef _OPENMP
-
574 # pragma omp parallel \
-
575  default (none) \
-
576  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
577  qureg,numTasks,targetQubit) \
-
578  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
579  thisIndexInInnerBlock,outerBit)
-
580 # endif
-
581  {
-
582 # ifdef _OPENMP
-
583 # pragma omp for schedule (static)
+
516  //printf("rank: %d err: %d\n", qureg.rank, err);
+
517  MPI_Sendrecv(&qureg.stateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL, pairRank, TAG,
+
518  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
+
519  pairRank, TAG, MPI_COMM_WORLD, &status);
+
520  }
+
521 }
+
522 
+
523 void exchangePairStateVectorHalves(Qureg qureg, int pairRank){
+
524  // MPI send/receive vars
+
525  int TAG=100;
+
526  MPI_Status status;
+
527  long long int numAmpsToSend = qureg.numAmpsPerChunk >> 1;
+
528 
+
529  // Multiple messages are required as MPI uses int rather than long long int for count
+
530  // For openmpi, messages are further restricted to 2GB in size -- do this for all cases
+
531  // to be safe
+
532  long long int maxMessageCount = MPI_MAX_AMPS_IN_MSG;
+
533  if (numAmpsToSend < maxMessageCount)
+
534  maxMessageCount = numAmpsToSend;
+
535 
+
536  // safely assume MPI_MAX... = 2^n, so division always exact
+
537  int numMessages = numAmpsToSend/maxMessageCount;
+
538  int i;
+
539  long long int offset;
+
540  // send the bottom half of my state vector to the top half of pairRank's qureg.pairStateVec
+
541  // receive pairRank's state vector into the top of qureg.pairStateVec
+
542  for (i=0; i<numMessages; i++){
+
543  offset = i*maxMessageCount;
+
544  MPI_Sendrecv(&qureg.pairStateVec.real[offset+numAmpsToSend], maxMessageCount,
+
545  MPI_QuEST_REAL, pairRank, TAG,
+
546  &qureg.pairStateVec.real[offset], maxMessageCount, MPI_QuEST_REAL,
+
547  pairRank, TAG, MPI_COMM_WORLD, &status);
+
548  //printf("rank: %d err: %d\n", qureg.rank, err);
+
549  MPI_Sendrecv(&qureg.pairStateVec.imag[offset+numAmpsToSend], maxMessageCount,
+
550  MPI_QuEST_REAL, pairRank, TAG,
+
551  &qureg.pairStateVec.imag[offset], maxMessageCount, MPI_QuEST_REAL,
+
552  pairRank, TAG, MPI_COMM_WORLD, &status);
+
553  }
+
554 }
+
555 
+
556 // @todo decide where this function should go. It is a preparation for MPI data transfer function
+ +
558  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
559  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
560  long long int thisInnerBlock, // current block
+
561  thisOuterColumn, // current column in density matrix
+
562  thisIndex, // current index in (density matrix representation) state vector
+
563  thisIndexInOuterColumn,
+
564  thisIndexInInnerBlock;
+
565 
+
566  int outerBit;
+
567 
+
568  long long int thisTask;
+
569  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
570 
+
571  // set dimensions
+
572  sizeInnerHalfBlock = 1LL << targetQubit;
+
573  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
574  sizeOuterHalfColumn = 1LL << qureg.numQubitsRepresented;
+
575  sizeOuterColumn = 2LL * sizeOuterHalfColumn;
+
576 
+
577 # ifdef _OPENMP
+
578 # pragma omp parallel \
+
579  default (none) \
+
580  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
581  qureg,numTasks,targetQubit) \
+
582  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
583  thisIndexInInnerBlock,outerBit)
584 # endif
-
585  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
586  // treat this as iterating over all columns, then iterating over half the values
-
587  // within one column.
-
588  // If this function has been called, this process' chunk contains half an
-
589  // outer block or less
-
590  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
591  // we want to process all columns in the density matrix,
-
592  // updating the values for half of each column (one half of each inner block)
-
593  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
594  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
595  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
596  // get index in state vector corresponding to upper inner block
-
597  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
598  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
599  + thisIndexInInnerBlock;
-
600  // check if we are in the upper or lower half of an outer block
-
601  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
602  // if we are in the lower half of an outer block, shift to be in the lower half
-
603  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
604  thisIndex += outerBit*(sizeInnerHalfBlock);
-
605 
-
606  // NOTE: at this point thisIndex should be the index of the element we want to
-
607  // dephase in the chunk of the state vector on this process, in the
-
608  // density matrix representation.
-
609  // thisTask is the index of the pair element in pairStateVec
-
610  // we will populate the second half of pairStateVec with this process'
-
611  // data to send
-
612 
-
613  qureg.pairStateVec.real[thisTask+numTasks] = qureg.stateVec.real[thisIndex];
-
614  qureg.pairStateVec.imag[thisTask+numTasks] = qureg.stateVec.imag[thisIndex];
-
615 
-
616  }
-
617  }
-
618 }
+
585  {
+
586 # ifdef _OPENMP
+
587 # pragma omp for schedule (static)
+
588 # endif
+
589  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
590  // treat this as iterating over all columns, then iterating over half the values
+
591  // within one column.
+
592  // If this function has been called, this process' chunk contains half an
+
593  // outer block or less
+
594  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
595  // we want to process all columns in the density matrix,
+
596  // updating the values for half of each column (one half of each inner block)
+
597  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
598  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
599  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
600  // get index in state vector corresponding to upper inner block
+
601  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
602  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
603  + thisIndexInInnerBlock;
+
604  // check if we are in the upper or lower half of an outer block
+
605  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
606  // if we are in the lower half of an outer block, shift to be in the lower half
+
607  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
608  thisIndex += outerBit*(sizeInnerHalfBlock);
+
609 
+
610  // NOTE: at this point thisIndex should be the index of the element we want to
+
611  // dephase in the chunk of the state vector on this process, in the
+
612  // density matrix representation.
+
613  // thisTask is the index of the pair element in pairStateVec
+
614  // we will populate the second half of pairStateVec with this process'
+
615  // data to send
+
616 
+
617  qureg.pairStateVec.real[thisTask+numTasks] = qureg.stateVec.real[thisIndex];
+
618  qureg.pairStateVec.imag[thisTask+numTasks] = qureg.stateVec.imag[thisIndex];
619 
-
620 void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit,
-
621  int qubit2) {
-
622 
-
623  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
624  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
625  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
626  long long int
-
627  thisInnerBlockQ2,
-
628  thisOuterColumn, // current column in density matrix
-
629  thisIndex, // current index in (density matrix representation) state vector
-
630  thisIndexInOuterColumn,
-
631  thisIndexInInnerBlockQ1,
-
632  thisIndexInInnerBlockQ2,
-
633  thisInnerBlockQ1InInnerBlockQ2;
-
634  int outerBitQ1, outerBitQ2;
-
635 
-
636  long long int thisTask;
-
637  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
638 
-
639  // set dimensions
-
640  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
641  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
642  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
643  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
644  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
645  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
646  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
647 
-
648 # ifdef _OPENMP
-
649 # pragma omp parallel \
-
650  default (none) \
-
651  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerQuarterBlockQ2,sizeInnerHalfBlockQ2,sizeInnerBlockQ2, \
-
652  sizeOuterColumn,sizeOuterQuarterColumn,qureg,numTasks,targetQubit,qubit2) \
-
653  private (thisTask,thisInnerBlockQ2,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
654  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2,outerBitQ1,outerBitQ2)
-
655 # endif
-
656  {
-
657 # ifdef _OPENMP
-
658 # pragma omp for schedule (static)
+
620  }
+
621  }
+
622 }
+
623 
+
624 void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit,
+
625  int qubit2) {
+
626 
+
627  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
628  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
629  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
630  long long int
+
631  thisInnerBlockQ2,
+
632  thisOuterColumn, // current column in density matrix
+
633  thisIndex, // current index in (density matrix representation) state vector
+
634  thisIndexInOuterColumn,
+
635  thisIndexInInnerBlockQ1,
+
636  thisIndexInInnerBlockQ2,
+
637  thisInnerBlockQ1InInnerBlockQ2;
+
638  int outerBitQ1, outerBitQ2;
+
639 
+
640  long long int thisTask;
+
641  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
642 
+
643  // set dimensions
+
644  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
645  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
646  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
647  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
648  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
649  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
650  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
651 
+
652 # ifdef _OPENMP
+
653 # pragma omp parallel \
+
654  default (none) \
+
655  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerQuarterBlockQ2,sizeInnerHalfBlockQ2,sizeInnerBlockQ2, \
+
656  sizeOuterColumn,sizeOuterQuarterColumn,qureg,numTasks,targetQubit,qubit2) \
+
657  private (thisTask,thisInnerBlockQ2,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
658  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2,outerBitQ1,outerBitQ2)
659 # endif
-
660  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
661  // treat this as iterating over all columns, then iterating over half the values
-
662  // within one column.
-
663  // If this function has been called, this process' chunk contains half an
-
664  // outer block or less
-
665  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
666  // we want to process all columns in the density matrix,
-
667  // updating the values for half of each column (one half of each inner block)
-
668  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
669  // thisTask % sizeOuterQuarterColumn
-
670  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
671  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
672  // thisTask % sizeInnerQuarterBlockQ2;
-
673  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
674  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
675  // thisTask % sizeInnerHalfBlockQ1;
-
676  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
677 
-
678  // get index in state vector corresponding to upper inner block
-
679  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
680  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
660  {
+
661 # ifdef _OPENMP
+
662 # pragma omp for schedule (static)
+
663 # endif
+
664  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
665  // treat this as iterating over all columns, then iterating over half the values
+
666  // within one column.
+
667  // If this function has been called, this process' chunk contains half an
+
668  // outer block or less
+
669  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
670  // we want to process all columns in the density matrix,
+
671  // updating the values for half of each column (one half of each inner block)
+
672  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
673  // thisTask % sizeOuterQuarterColumn
+
674  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
675  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
676  // thisTask % sizeInnerQuarterBlockQ2;
+
677  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
678  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
679  // thisTask % sizeInnerHalfBlockQ1;
+
680  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
681 
-
682  // check if we are in the upper or lower half of an outer block for Q1
-
683  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
684  // if we are in the lower half of an outer block, shift to be in the lower half
-
685  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
686  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
687 
-
688  // check if we are in the upper or lower half of an outer block for Q2
-
689  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
690  // if we are in the lower half of an outer block, shift to be in the lower half
-
691  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
692  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
-
693 
-
694  // NOTE: at this point thisIndex should be the index of the element we want to
-
695  // dephase in the chunk of the state vector on this process, in the
-
696  // density matrix representation.
-
697  // thisTask is the index of the pair element in pairStateVec
-
698 
-
699  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
700  // + pair[thisTask])/2
-
701  qureg.pairStateVec.real[thisTask+numTasks*2] = qureg.stateVec.real[thisIndex];
-
702  qureg.pairStateVec.imag[thisTask+numTasks*2] = qureg.stateVec.imag[thisIndex];
-
703  }
-
704  }
-
705 }
-
706 
-
707 
-
708 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
-
709  if (depolLevel == 0)
-
710  return;
-
711 
-
712  int rankIsUpper; // rank is in the upper half of an outer block
-
713  int pairRank; // rank of corresponding chunk
-
714 
-
715  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
716  qureg.numQubitsRepresented, targetQubit);
-
717 
-
718  if (useLocalDataOnly){
-
719  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
720  } else {
-
721  // pack data to send to my pair process into the first half of pairStateVec
-
722  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
723 
-
724  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
725  qureg.numQubitsRepresented);
-
726  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
727  targetQubit, qureg.numQubitsRepresented);
-
728 
-
729  exchangePairStateVectorHalves(qureg, pairRank);
-
730  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
-
731  }
+
682  // get index in state vector corresponding to upper inner block
+
683  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
684  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
685 
+
686  // check if we are in the upper or lower half of an outer block for Q1
+
687  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
688  // if we are in the lower half of an outer block, shift to be in the lower half
+
689  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
690  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+
691 
+
692  // check if we are in the upper or lower half of an outer block for Q2
+
693  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
694  // if we are in the lower half of an outer block, shift to be in the lower half
+
695  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
696  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
697 
+
698  // NOTE: at this point thisIndex should be the index of the element we want to
+
699  // dephase in the chunk of the state vector on this process, in the
+
700  // density matrix representation.
+
701  // thisTask is the index of the pair element in pairStateVec
+
702 
+
703  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
704  // + pair[thisTask])/2
+
705  qureg.pairStateVec.real[thisTask+numTasks*2] = qureg.stateVec.real[thisIndex];
+
706  qureg.pairStateVec.imag[thisTask+numTasks*2] = qureg.stateVec.imag[thisIndex];
+
707  }
+
708  }
+
709 }
+
710 
+
711 
+
712 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
+
713  if (depolLevel == 0)
+
714  return;
+
715 
+
716  int rankIsUpper; // rank is in the upper half of an outer block
+
717  int pairRank; // rank of corresponding chunk
+
718 
+
719  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
720  qureg.numQubitsRepresented, targetQubit);
+
721 
+
722  if (useLocalDataOnly){
+
723  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
+
724  } else {
+
725  // pack data to send to my pair process into the first half of pairStateVec
+
726  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
+
727 
+
728  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
+
729  qureg.numQubitsRepresented);
+
730  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
+
731  targetQubit, qureg.numQubitsRepresented);
732 
-
733 }
-
734 
-
735 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
-
736  if (damping == 0)
-
737  return;
-
738 
-
739  int rankIsUpper; // rank is in the upper half of an outer block
-
740  int pairRank; // rank of corresponding chunk
-
741 
-
742  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
743  qureg.numQubitsRepresented, targetQubit);
-
744 
-
745  if (useLocalDataOnly){
-
746  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
747  } else {
-
748  // pack data to send to my pair process into the first half of pairStateVec
-
749  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
750 
-
751  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
752  qureg.numQubitsRepresented);
-
753  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
754  targetQubit, qureg.numQubitsRepresented);
-
755 
-
756  exchangePairStateVectorHalves(qureg, pairRank);
-
757  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
-
758  }
+
733  exchangePairStateVectorHalves(qureg, pairRank);
+
734  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
+
735  }
+
736 
+
737 }
+
738 
+
739 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
+
740  if (damping == 0)
+
741  return;
+
742 
+
743  int rankIsUpper; // rank is in the upper half of an outer block
+
744  int pairRank; // rank of corresponding chunk
+
745 
+
746  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
747  qureg.numQubitsRepresented, targetQubit);
+
748 
+
749  if (useLocalDataOnly){
+
750  densmatr_mixDampingLocal(qureg, targetQubit, damping);
+
751  } else {
+
752  // pack data to send to my pair process into the first half of pairStateVec
+
753  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
+
754 
+
755  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
+
756  qureg.numQubitsRepresented);
+
757  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
+
758  targetQubit, qureg.numQubitsRepresented);
759 
-
760 }
-
761 
-
762 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel){
-
763  if (depolLevel == 0)
-
764  return;
-
765  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
-
766  int pairRank; // rank of corresponding chunk
-
767  int biggerQubit, smallerQubit;
-
768 
-
769  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
770 
-
771  qreal eta = 2/depolLevel;
-
772  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
773  qreal gamma = 1+delta;
-
774  gamma = 1/(gamma*gamma*gamma);
-
775  qreal GAMMA_PARTS_1_OR_2 = 1.0;
-
776  // TODO -- test delta too small
-
777  /*
-
778  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
-
779  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
-
780  exit(1);
-
781  }
-
782  */
-
783 
-
784  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
-
785  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
-
786  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
-
787 
-
788  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
789  qureg.numQubitsRepresented, biggerQubit);
-
790  if (useLocalDataOnlyBigQubit){
-
791  // does parts 1, 2 and 3 locally in one go
-
792  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
793  } else {
-
794  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
795  qureg.numQubitsRepresented, smallerQubit);
-
796  if (useLocalDataOnlySmallQubit){
-
797  // do part 1 locally
-
798  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
-
799 
-
800  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
-
801  // part 2 will be distributed and the value of the small qubit won't matter
-
802  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
803  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
804  qureg.numQubitsRepresented);
-
805  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
806  biggerQubit, qureg.numQubitsRepresented);
-
807 
-
808  exchangePairStateVectorHalves(qureg, pairRank);
-
809  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
810 
-
811  // part 3 will be distributed but involve rearranging for the smaller qubit
-
812  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
813  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
814  qureg.numQubitsRepresented);
-
815  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
816  biggerQubit, qureg.numQubitsRepresented);
-
817 
-
818  exchangePairStateVectorHalves(qureg, pairRank);
-
819  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
-
820  } else {
-
821  // do part 1, 2 and 3 distributed
-
822  // part 1
-
823  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
824  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
-
825  qureg.numQubitsRepresented);
-
826  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
827  smallerQubit, qureg.numQubitsRepresented);
-
828 
-
829  exchangePairStateVectorHalves(qureg, pairRank);
-
830  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
831 
-
832  // part 2
-
833  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
834  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
835  qureg.numQubitsRepresented);
-
836  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
837  biggerQubit, qureg.numQubitsRepresented);
-
838 
-
839  exchangePairStateVectorHalves(qureg, pairRank);
-
840  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
841 
-
842  // part 3
-
843  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
844  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
-
845  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
-
846  exchangePairStateVectorHalves(qureg, pairRank);
-
847  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
-
848 
-
849  }
-
850  }
-
851 
-
852 }
-
853 
-
854 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
855 {
-
856  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
857  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
858  Complex rot1, rot2;
-
859 
-
860  // rank's chunk is in upper half of block
-
861  int rankIsUpper;
-
862  int pairRank; // rank of corresponding chunk
+
760  exchangePairStateVectorHalves(qureg, pairRank);
+
761  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
+
762  }
+
763 
+
764 }
+
765 
+
766 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel){
+
767  if (depolLevel == 0)
+
768  return;
+
769  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
+
770  int pairRank; // rank of corresponding chunk
+
771  int biggerQubit, smallerQubit;
+
772 
+
773  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
774 
+
775  qreal eta = 2/depolLevel;
+
776  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
+
777  qreal gamma = 1+delta;
+
778  gamma = 1/(gamma*gamma*gamma);
+
779  qreal GAMMA_PARTS_1_OR_2 = 1.0;
+
780  // TODO -- test delta too small
+
781  /*
+
782  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
+
783  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
+
784  exit(1);
+
785  }
+
786  */
+
787 
+
788  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
+
789  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
+
790  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
+
791 
+
792  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
793  qureg.numQubitsRepresented, biggerQubit);
+
794  if (useLocalDataOnlyBigQubit){
+
795  // does parts 1, 2 and 3 locally in one go
+
796  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
+
797  } else {
+
798  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
799  qureg.numQubitsRepresented, smallerQubit);
+
800  if (useLocalDataOnlySmallQubit){
+
801  // do part 1 locally
+
802  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
+
803 
+
804  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
+
805  // part 2 will be distributed and the value of the small qubit won't matter
+
806  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
807  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
808  qureg.numQubitsRepresented);
+
809  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
810  biggerQubit, qureg.numQubitsRepresented);
+
811 
+
812  exchangePairStateVectorHalves(qureg, pairRank);
+
813  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
814 
+
815  // part 3 will be distributed but involve rearranging for the smaller qubit
+
816  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
817  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
818  qureg.numQubitsRepresented);
+
819  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
820  biggerQubit, qureg.numQubitsRepresented);
+
821 
+
822  exchangePairStateVectorHalves(qureg, pairRank);
+
823  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
+
824  } else {
+
825  // do part 1, 2 and 3 distributed
+
826  // part 1
+
827  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
828  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
+
829  qureg.numQubitsRepresented);
+
830  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
831  smallerQubit, qureg.numQubitsRepresented);
+
832 
+
833  exchangePairStateVectorHalves(qureg, pairRank);
+
834  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
835 
+
836  // part 2
+
837  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
838  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
839  qureg.numQubitsRepresented);
+
840  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
841  biggerQubit, qureg.numQubitsRepresented);
+
842 
+
843  exchangePairStateVectorHalves(qureg, pairRank);
+
844  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
845 
+
846  // part 3
+
847  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
848  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
+
849  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
+
850  exchangePairStateVectorHalves(qureg, pairRank);
+
851  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
+
852 
+
853  }
+
854  }
+
855 
+
856 }
+
857 
+
858 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
859 {
+
860  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
861  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
862  Complex rot1, rot2;
863 
-
864  if (useLocalDataOnly){
-
865  // all values required to update state vector lie in this rank
-
866  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
867  } else {
-
868  // need to get corresponding chunk of state vector from other rank
-
869  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
870  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
871  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
872  // get corresponding values from my pair
-
873  exchangeStateVectors(qureg, pairRank);
-
874 
-
875  // this rank's values are either in the upper of lower half of the block.
-
876  // send values to compactUnitaryDistributed in the correct order
-
877  if (rankIsUpper){
-
878  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
879  qureg.stateVec, //upper
-
880  qureg.pairStateVec, //lower
-
881  qureg.stateVec); //output
-
882  } else {
-
883  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
884  qureg.pairStateVec, //upper
-
885  qureg.stateVec, //lower
-
886  qureg.stateVec); //output
-
887  }
-
888  }
-
889 }
-
890 
-
891 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
892 {
-
893  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
894  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
895  Complex rot1, rot2;
-
896 
-
897  // rank's chunk is in upper half of block
-
898  int rankIsUpper;
-
899  int pairRank; // rank of corresponding chunk
+
864  // rank's chunk is in upper half of block
+
865  int rankIsUpper;
+
866  int pairRank; // rank of corresponding chunk
+
867 
+
868  if (useLocalDataOnly){
+
869  // all values required to update state vector lie in this rank
+
870  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
+
871  } else {
+
872  // need to get corresponding chunk of state vector from other rank
+
873  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
874  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
+
875  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
876  // get corresponding values from my pair
+
877  exchangeStateVectors(qureg, pairRank);
+
878 
+
879  // this rank's values are either in the upper of lower half of the block.
+
880  // send values to compactUnitaryDistributed in the correct order
+
881  if (rankIsUpper){
+
882  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
+
883  qureg.stateVec, //upper
+
884  qureg.pairStateVec, //lower
+
885  qureg.stateVec); //output
+
886  } else {
+
887  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
+
888  qureg.pairStateVec, //upper
+
889  qureg.stateVec, //lower
+
890  qureg.stateVec); //output
+
891  }
+
892  }
+
893 }
+
894 
+
895 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
896 {
+
897  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
898  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
899  Complex rot1, rot2;
900 
-
901  if (useLocalDataOnly){
-
902  // all values required to update state vector lie in this rank
-
903  statevec_unitaryLocal(qureg, targetQubit, u);
-
904  } else {
-
905  // need to get corresponding chunk of state vector from other rank
-
906  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
907  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
908  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
909  // get corresponding values from my pair
-
910  exchangeStateVectors(qureg, pairRank);
-
911 
-
912  // this rank's values are either in the upper of lower half of the block.
-
913  // send values to compactUnitaryDistributed in the correct order
-
914  if (rankIsUpper){
-
915  statevec_unitaryDistributed(qureg,rot1,rot2,
-
916  qureg.stateVec, //upper
-
917  qureg.pairStateVec, //lower
-
918  qureg.stateVec); //output
-
919  } else {
-
920  statevec_unitaryDistributed(qureg,rot1,rot2,
-
921  qureg.pairStateVec, //upper
-
922  qureg.stateVec, //lower
-
923  qureg.stateVec); //output
-
924  }
-
925  }
-
926 
-
927 
-
928 }
-
929 
-
930 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
931 {
-
932  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
933  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
934  Complex rot1, rot2;
-
935 
-
936  // rank's chunk is in upper half of block
-
937  int rankIsUpper;
-
938  int pairRank; // rank of corresponding chunk
+
901  // rank's chunk is in upper half of block
+
902  int rankIsUpper;
+
903  int pairRank; // rank of corresponding chunk
+
904 
+
905  if (useLocalDataOnly){
+
906  // all values required to update state vector lie in this rank
+
907  statevec_unitaryLocal(qureg, targetQubit, u);
+
908  } else {
+
909  // need to get corresponding chunk of state vector from other rank
+
910  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
911  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
912  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
913  // get corresponding values from my pair
+
914  exchangeStateVectors(qureg, pairRank);
+
915 
+
916  // this rank's values are either in the upper of lower half of the block.
+
917  // send values to compactUnitaryDistributed in the correct order
+
918  if (rankIsUpper){
+
919  statevec_unitaryDistributed(qureg,rot1,rot2,
+
920  qureg.stateVec, //upper
+
921  qureg.pairStateVec, //lower
+
922  qureg.stateVec); //output
+
923  } else {
+
924  statevec_unitaryDistributed(qureg,rot1,rot2,
+
925  qureg.pairStateVec, //upper
+
926  qureg.stateVec, //lower
+
927  qureg.stateVec); //output
+
928  }
+
929  }
+
930 
+
931 
+
932 }
+
933 
+
934 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
935 {
+
936  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
937  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
938  Complex rot1, rot2;
939 
-
940  if (useLocalDataOnly){
-
941  // all values required to update state vector lie in this rank
-
942  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
943  } else {
-
944  // need to get corresponding chunk of state vector from other rank
-
945  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
946  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
947  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
948  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
949  // get corresponding values from my pair
-
950  exchangeStateVectors(qureg, pairRank);
-
951 
-
952  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
-
953  // in the correct order
-
954  if (rankIsUpper){
-
955  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
956  qureg.stateVec, //upper
-
957  qureg.pairStateVec, //lower
-
958  qureg.stateVec); //output
-
959  } else {
-
960  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
961  qureg.pairStateVec, //upper
-
962  qureg.stateVec, //lower
-
963  qureg.stateVec); //output
-
964  }
-
965  }
-
966 }
-
967 
-
968 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit,
-
969  ComplexMatrix2 u)
-
970 {
-
971  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
972  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
973  Complex rot1, rot2;
-
974 
-
975  // rank's chunk is in upper half of block
-
976  int rankIsUpper;
-
977  int pairRank; // rank of corresponding chunk
+
940  // rank's chunk is in upper half of block
+
941  int rankIsUpper;
+
942  int pairRank; // rank of corresponding chunk
+
943 
+
944  if (useLocalDataOnly){
+
945  // all values required to update state vector lie in this rank
+
946  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
+
947  } else {
+
948  // need to get corresponding chunk of state vector from other rank
+
949  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
950  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
+
951  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
952  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
953  // get corresponding values from my pair
+
954  exchangeStateVectors(qureg, pairRank);
+
955 
+
956  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
+
957  // in the correct order
+
958  if (rankIsUpper){
+
959  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
960  qureg.stateVec, //upper
+
961  qureg.pairStateVec, //lower
+
962  qureg.stateVec); //output
+
963  } else {
+
964  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
965  qureg.pairStateVec, //upper
+
966  qureg.stateVec, //lower
+
967  qureg.stateVec); //output
+
968  }
+
969  }
+
970 }
+
971 
+
972 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit,
+
973  ComplexMatrix2 u)
+
974 {
+
975  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
976  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
977  Complex rot1, rot2;
978 
-
979  if (useLocalDataOnly){
-
980  // all values required to update state vector lie in this rank
-
981  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
982  } else {
-
983  // need to get corresponding chunk of state vector from other rank
-
984  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
985  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
986  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
987  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
988  // get corresponding values from my pair
-
989  exchangeStateVectors(qureg, pairRank);
-
990 
-
991  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
-
992  // in the correct order
-
993  if (rankIsUpper){
-
994  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
995  qureg.stateVec, //upper
-
996  qureg.pairStateVec, //lower
-
997  qureg.stateVec); //output
-
998  } else {
-
999  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
1000  qureg.pairStateVec, //upper
-
1001  qureg.stateVec, //lower
-
1002  qureg.stateVec); //output
-
1003  }
-
1004  }
-
1005 }
-
1006 
-
1007 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
1008 {
-
1009  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1010  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1011  Complex rot1, rot2;
-
1012 
-
1013  // rank's chunk is in upper half of block
-
1014  int rankIsUpper;
-
1015  int pairRank; // rank of corresponding chunk
+
979  // rank's chunk is in upper half of block
+
980  int rankIsUpper;
+
981  int pairRank; // rank of corresponding chunk
+
982 
+
983  if (useLocalDataOnly){
+
984  // all values required to update state vector lie in this rank
+
985  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
+
986  } else {
+
987  // need to get corresponding chunk of state vector from other rank
+
988  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
989  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
990  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
991  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
992  // get corresponding values from my pair
+
993  exchangeStateVectors(qureg, pairRank);
+
994 
+
995  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
+
996  // in the correct order
+
997  if (rankIsUpper){
+
998  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
999  qureg.stateVec, //upper
+
1000  qureg.pairStateVec, //lower
+
1001  qureg.stateVec); //output
+
1002  } else {
+
1003  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
1004  qureg.pairStateVec, //upper
+
1005  qureg.stateVec, //lower
+
1006  qureg.stateVec); //output
+
1007  }
+
1008  }
+
1009 }
+
1010 
+
1011 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
1012 {
+
1013  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1014  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1015  Complex rot1, rot2;
1016 
-
1017  if (useLocalDataOnly){
-
1018  // all values required to update state vector lie in this rank
-
1019  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
1020  } else {
-
1021  // need to get corresponding chunk of state vector from other rank
-
1022  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1023  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
1024  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1025 
-
1026  // get corresponding values from my pair
-
1027  exchangeStateVectors(qureg, pairRank);
-
1028 
-
1029  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
-
1030  // in the correct order
-
1031  if (rankIsUpper){
-
1032  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1033  qureg.stateVec, //upper
-
1034  qureg.pairStateVec, //lower
-
1035  qureg.stateVec); //output
-
1036  } else {
-
1037  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1038  qureg.pairStateVec, //upper
-
1039  qureg.stateVec, //lower
-
1040  qureg.stateVec); //output
-
1041  }
-
1042  }
-
1043 }
-
1044 void statevec_pauliX(Qureg qureg, int targetQubit)
-
1045 {
-
1046  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1047  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1048 
-
1049  // rank's chunk is in upper half of block
-
1050  int rankIsUpper;
-
1051  int pairRank; // rank of corresponding chunk
+
1017  // rank's chunk is in upper half of block
+
1018  int rankIsUpper;
+
1019  int pairRank; // rank of corresponding chunk
+
1020 
+
1021  if (useLocalDataOnly){
+
1022  // all values required to update state vector lie in this rank
+
1023  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
+
1024  } else {
+
1025  // need to get corresponding chunk of state vector from other rank
+
1026  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1027  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
1028  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1029 
+
1030  // get corresponding values from my pair
+
1031  exchangeStateVectors(qureg, pairRank);
+
1032 
+
1033  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
+
1034  // in the correct order
+
1035  if (rankIsUpper){
+
1036  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
+
1037  qureg.stateVec, //upper
+
1038  qureg.pairStateVec, //lower
+
1039  qureg.stateVec); //output
+
1040  } else {
+
1041  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
+
1042  qureg.pairStateVec, //upper
+
1043  qureg.stateVec, //lower
+
1044  qureg.stateVec); //output
+
1045  }
+
1046  }
+
1047 }
+
1048 void statevec_pauliX(Qureg qureg, int targetQubit)
+
1049 {
+
1050  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1051  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1052 
-
1053  if (useLocalDataOnly){
-
1054  // all values required to update state vector lie in this rank
-
1055  statevec_pauliXLocal(qureg, targetQubit);
-
1056  } else {
-
1057  // need to get corresponding chunk of state vector from other rank
-
1058  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1059  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1060  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1061  // get corresponding values from my pair
-
1062  exchangeStateVectors(qureg, pairRank);
-
1063  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
-
1064  // this rank's values with pair values
- -
1066  qureg.pairStateVec, // in
-
1067  qureg.stateVec); // out
-
1068  }
-
1069 }
-
1070 
-
1071 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
1072 {
-
1073  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1074  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1075  int rankIsUpper; // rank's chunk is in upper half of block
-
1076  int pairRank; // rank of corresponding chunk
-
1077 
-
1078  if (useLocalDataOnly){
-
1079  // all values required to update state vector lie in this rank
-
1080  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
1081  } else {
-
1082  // need to get corresponding chunk of state vector from other rank
-
1083  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1084  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1085  // get corresponding values from my pair
-
1086  exchangeStateVectors(qureg, pairRank);
-
1087  statevec_controlledNotDistributed(qureg,controlQubit,
-
1088  qureg.pairStateVec, //in
-
1089  qureg.stateVec); //out
-
1090  }
-
1091 }
-
1092 
-
1093 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
-
1094 {
-
1095  /* operation is the same regardless of control and target ordering, hence
-
1096  * we accept only bitMasks (for convenience of caller, when shifting qubits
-
1097  * for density matrices)
-
1098  */
-
1099 
-
1100  // global index of the first basis state in this node
-
1101  long long int firstInd = qureg.chunkId * qureg.numAmpsPerChunk;
-
1102 
-
1103  /* optimisation: if this node doesn't contain any amplitudes for which {ctrls}={1}
-
1104  * (and hence, neither does the pair node), then these pair nodes have nothing to modify
-
1105  * nor any need to communicate, and can halt. No ctrls are contained in the node
-
1106  * if the distance from the first index, to the next index where {ctrls}=1, is
-
1107  * greater than the total contained amplitudes. This is a worthwhile optimisation,
-
1108  * since although we must still wait for the slowest node, we have potentially reduced
-
1109  * the network traffic and might avoid saturation.
-
1110  */
-
1111  if ((firstInd|ctrlMask) - firstInd >= qureg.numAmpsPerChunk)
-
1112  return;
-
1113 
-
1114  /* nodes communicate pairwise, and (ignoring ctrls) swap all their amplitudes with mate.
-
1115  * hence we find |pairState> = X_{targs}|firstStateInNode>, determine which node contains
-
1116  * |pairState>, and swap state-vector with it (unless it happens to be this node).
-
1117  */
-
1118 
-
1119  // global index of the corresponding NOT'd first basis state
-
1120  long long int pairInd = firstInd ^ targMask;
-
1121  int pairRank = pairInd / qureg.numAmpsPerChunk;
-
1122  int useLocalDataOnly = (pairRank == qureg.chunkId);
-
1123 
-
1124  if (useLocalDataOnly) {
-
1125  // swaps amplitudes locally, setting |a>=X|b>, and |b>=X|a>
-
1126  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
-
1127  } else {
-
1128  // swaps amplitudes with pair node
-
1129  exchangeStateVectors(qureg, pairRank);
-
1130  // modifies only |a>=X|b> (pair node handles the converse)
- -
1132  qureg, ctrlMask, targMask,
-
1133  qureg.pairStateVec, // in
-
1134  qureg.stateVec); // out
-
1135  }
-
1136 }
-
1137 
-
1138 void statevec_pauliY(Qureg qureg, int targetQubit)
-
1139 {
-
1140  int conjFac = 1;
+
1053  // rank's chunk is in upper half of block
+
1054  int rankIsUpper;
+
1055  int pairRank; // rank of corresponding chunk
+
1056 
+
1057  if (useLocalDataOnly){
+
1058  // all values required to update state vector lie in this rank
+
1059  statevec_pauliXLocal(qureg, targetQubit);
+
1060  } else {
+
1061  // need to get corresponding chunk of state vector from other rank
+
1062  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1063  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1064  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
1065  // get corresponding values from my pair
+
1066  exchangeStateVectors(qureg, pairRank);
+
1067  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
+
1068  // this rank's values with pair values
+ +
1070  qureg.pairStateVec, // in
+
1071  qureg.stateVec); // out
+
1072  }
+
1073 }
+
1074 
+
1075 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
1076 {
+
1077  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1078  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1079  int rankIsUpper; // rank's chunk is in upper half of block
+
1080  int pairRank; // rank of corresponding chunk
+
1081 
+
1082  if (useLocalDataOnly){
+
1083  // all values required to update state vector lie in this rank
+
1084  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
+
1085  } else {
+
1086  // need to get corresponding chunk of state vector from other rank
+
1087  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1088  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1089  // get corresponding values from my pair
+
1090  exchangeStateVectors(qureg, pairRank);
+
1091  statevec_controlledNotDistributed(qureg,controlQubit,
+
1092  qureg.pairStateVec, //in
+
1093  qureg.stateVec); //out
+
1094  }
+
1095 }
+
1096 
+
1097 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
+
1098 {
+
1099  /* operation is the same regardless of control and target ordering, hence
+
1100  * we accept only bitMasks (for convenience of caller, when shifting qubits
+
1101  * for density matrices)
+
1102  */
+
1103 
+
1104  // global index of the first basis state in this node
+
1105  long long int firstInd = qureg.chunkId * qureg.numAmpsPerChunk;
+
1106 
+
1107  /* optimisation: if this node doesn't contain any amplitudes for which {ctrls}={1}
+
1108  * (and hence, neither does the pair node), then these pair nodes have nothing to modify
+
1109  * nor any need to communicate, and can halt. No ctrls are contained in the node
+
1110  * if the distance from the first index, to the next index where {ctrls}=1, is
+
1111  * greater than the total contained amplitudes. This is a worthwhile optimisation,
+
1112  * since although we must still wait for the slowest node, we have potentially reduced
+
1113  * the network traffic and might avoid saturation.
+
1114  */
+
1115  if ((firstInd|ctrlMask) - firstInd >= qureg.numAmpsPerChunk)
+
1116  return;
+
1117 
+
1118  /* nodes communicate pairwise, and (ignoring ctrls) swap all their amplitudes with mate.
+
1119  * hence we find |pairState> = X_{targs}|firstStateInNode>, determine which node contains
+
1120  * |pairState>, and swap state-vector with it (unless it happens to be this node).
+
1121  */
+
1122 
+
1123  // global index of the corresponding NOT'd first basis state
+
1124  long long int pairInd = firstInd ^ targMask;
+
1125  int pairRank = pairInd / qureg.numAmpsPerChunk;
+
1126  int useLocalDataOnly = (pairRank == qureg.chunkId);
+
1127 
+
1128  if (useLocalDataOnly) {
+
1129  // swaps amplitudes locally, setting |a>=X|b>, and |b>=X|a>
+
1130  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
+
1131  } else {
+
1132  // swaps amplitudes with pair node
+
1133  exchangeStateVectors(qureg, pairRank);
+
1134  // modifies only |a>=X|b> (pair node handles the converse)
+ +
1136  qureg, ctrlMask, targMask,
+
1137  qureg.pairStateVec, // in
+
1138  qureg.stateVec); // out
+
1139  }
+
1140 }
1141 
-
1142  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1143  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1144  int rankIsUpper; // rank's chunk is in upper half of block
-
1145  int pairRank; // rank of corresponding chunk
-
1146 
-
1147  if (useLocalDataOnly){
-
1148  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1149  } else {
-
1150  // need to get corresponding chunk of state vector from other rank
-
1151  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1152  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1153  // get corresponding values from my pair
-
1154  exchangeStateVectors(qureg, pairRank);
-
1155  // this rank's values are either in the upper of lower half of the block
- -
1157  qureg.pairStateVec, // in
-
1158  qureg.stateVec, // out
-
1159  rankIsUpper, conjFac);
-
1160  }
-
1161 }
-
1162 
-
1163 void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
1164 {
-
1165  int conjFac = -1;
+
1142 void statevec_pauliY(Qureg qureg, int targetQubit)
+
1143 {
+
1144  int conjFac = 1;
+
1145 
+
1146  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1147  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1148  int rankIsUpper; // rank's chunk is in upper half of block
+
1149  int pairRank; // rank of corresponding chunk
+
1150 
+
1151  if (useLocalDataOnly){
+
1152  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
1153  } else {
+
1154  // need to get corresponding chunk of state vector from other rank
+
1155  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1156  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1157  // get corresponding values from my pair
+
1158  exchangeStateVectors(qureg, pairRank);
+
1159  // this rank's values are either in the upper of lower half of the block
+ +
1161  qureg.pairStateVec, // in
+
1162  qureg.stateVec, // out
+
1163  rankIsUpper, conjFac);
+
1164  }
+
1165 }
1166 
-
1167  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1168  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1169  int rankIsUpper; // rank's chunk is in upper half of block
-
1170  int pairRank; // rank of corresponding chunk
-
1171 
-
1172  if (useLocalDataOnly){
-
1173  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1174  } else {
-
1175  // need to get corresponding chunk of state vector from other rank
-
1176  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1177  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1178  // get corresponding values from my pair
-
1179  exchangeStateVectors(qureg, pairRank);
-
1180  // this rank's values are either in the upper of lower half of the block
- -
1182  qureg.pairStateVec, // in
-
1183  qureg.stateVec, // out
-
1184  rankIsUpper, conjFac);
-
1185  }
-
1186 }
-
1187 
-
1188 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
1189 {
-
1190  int conjFac = 1;
+
1167 void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
1168 {
+
1169  int conjFac = -1;
+
1170 
+
1171  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1172  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1173  int rankIsUpper; // rank's chunk is in upper half of block
+
1174  int pairRank; // rank of corresponding chunk
+
1175 
+
1176  if (useLocalDataOnly){
+
1177  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
1178  } else {
+
1179  // need to get corresponding chunk of state vector from other rank
+
1180  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1181  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1182  // get corresponding values from my pair
+
1183  exchangeStateVectors(qureg, pairRank);
+
1184  // this rank's values are either in the upper of lower half of the block
+ +
1186  qureg.pairStateVec, // in
+
1187  qureg.stateVec, // out
+
1188  rankIsUpper, conjFac);
+
1189  }
+
1190 }
1191 
-
1192  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1193  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1194  int rankIsUpper; // rank's chunk is in upper half of block
-
1195  int pairRank; // rank of corresponding chunk
-
1196 
-
1197  if (useLocalDataOnly){
-
1198  // all values required to update state vector lie in this rank
-
1199  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1200  } else {
-
1201  // need to get corresponding chunk of state vector from other rank
-
1202  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1203  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1204  // get corresponding values from my pair
-
1205  exchangeStateVectors(qureg, pairRank);
-
1206  // this rank's values are either in the upper of lower half of the block
-
1207  if (rankIsUpper){
-
1208  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1209  qureg.pairStateVec, //in
-
1210  qureg.stateVec,
-
1211  conjFac); //out
-
1212  } else {
-
1213  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1214  qureg.pairStateVec, //in
-
1215  qureg.stateVec,
-
1216  - conjFac); //out
-
1217  }
-
1218  }
-
1219 }
-
1220 
-
1221 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
1222 {
-
1223  int conjFac = -1;
+
1192 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
1193 {
+
1194  int conjFac = 1;
+
1195 
+
1196  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1197  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1198  int rankIsUpper; // rank's chunk is in upper half of block
+
1199  int pairRank; // rank of corresponding chunk
+
1200 
+
1201  if (useLocalDataOnly){
+
1202  // all values required to update state vector lie in this rank
+
1203  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
1204  } else {
+
1205  // need to get corresponding chunk of state vector from other rank
+
1206  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1207  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1208  // get corresponding values from my pair
+
1209  exchangeStateVectors(qureg, pairRank);
+
1210  // this rank's values are either in the upper of lower half of the block
+
1211  if (rankIsUpper){
+
1212  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1213  qureg.pairStateVec, //in
+
1214  qureg.stateVec,
+
1215  conjFac); //out
+
1216  } else {
+
1217  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1218  qureg.pairStateVec, //in
+
1219  qureg.stateVec,
+
1220  - conjFac); //out
+
1221  }
+
1222  }
+
1223 }
1224 
-
1225  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1226  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1227  int rankIsUpper; // rank's chunk is in upper half of block
-
1228  int pairRank; // rank of corresponding chunk
-
1229 
-
1230  if (useLocalDataOnly){
-
1231  // all values required to update state vector lie in this rank
-
1232  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1233  } else {
-
1234  // need to get corresponding chunk of state vector from other rank
-
1235  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1236  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1237  // get corresponding values from my pair
-
1238  exchangeStateVectors(qureg, pairRank);
-
1239  // this rank's values are either in the upper of lower half of the block
-
1240  if (rankIsUpper){
-
1241  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1242  qureg.pairStateVec, //in
-
1243  qureg.stateVec,
-
1244  conjFac); //out
-
1245  } else {
-
1246  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1247  qureg.pairStateVec, //in
-
1248  qureg.stateVec,
-
1249  - conjFac); //out
-
1250  }
-
1251  }
-
1252 }
-
1253 
-
1254 void statevec_hadamard(Qureg qureg, int targetQubit)
-
1255 {
-
1256  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1257  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1258 
-
1259  // rank's chunk is in upper half of block
-
1260  int rankIsUpper;
-
1261  int pairRank; // rank of corresponding chunk
+
1225 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
1226 {
+
1227  int conjFac = -1;
+
1228 
+
1229  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1230  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1231  int rankIsUpper; // rank's chunk is in upper half of block
+
1232  int pairRank; // rank of corresponding chunk
+
1233 
+
1234  if (useLocalDataOnly){
+
1235  // all values required to update state vector lie in this rank
+
1236  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
1237  } else {
+
1238  // need to get corresponding chunk of state vector from other rank
+
1239  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1240  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1241  // get corresponding values from my pair
+
1242  exchangeStateVectors(qureg, pairRank);
+
1243  // this rank's values are either in the upper of lower half of the block
+
1244  if (rankIsUpper){
+
1245  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1246  qureg.pairStateVec, //in
+
1247  qureg.stateVec,
+
1248  conjFac); //out
+
1249  } else {
+
1250  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1251  qureg.pairStateVec, //in
+
1252  qureg.stateVec,
+
1253  - conjFac); //out
+
1254  }
+
1255  }
+
1256 }
+
1257 
+
1258 void statevec_hadamard(Qureg qureg, int targetQubit)
+
1259 {
+
1260  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1261  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1262 
-
1263  if (useLocalDataOnly){
-
1264  // all values required to update state vector lie in this rank
-
1265  statevec_hadamardLocal(qureg, targetQubit);
-
1266  } else {
-
1267  // need to get corresponding chunk of state vector from other rank
-
1268  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1269  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1270  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1271  // get corresponding values from my pair
-
1272  exchangeStateVectors(qureg, pairRank);
-
1273  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
-
1274  // in the correct order
-
1275  if (rankIsUpper){
- -
1277  qureg.stateVec, //upper
-
1278  qureg.pairStateVec, //lower
-
1279  qureg.stateVec, rankIsUpper); //output
-
1280  } else {
- -
1282  qureg.pairStateVec, //upper
-
1283  qureg.stateVec, //lower
-
1284  qureg.stateVec, rankIsUpper); //output
-
1285  }
-
1286  }
-
1287 }
-
1288 
-
1299 static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
-
1300 {
-
1301  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1302  int numChunksToSkip = sizeHalfBlock/chunkSize;
-
1303  // calculate probability by summing over numChunksToSkip, then skipping numChunksToSkip, etc
-
1304  int bitToCheck = chunkId & numChunksToSkip;
-
1305  return bitToCheck;
-
1306 }
-
1307 
-
1308 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
1309 {
-
1310  qreal stateProb=0, totalStateProb=0;
-
1311  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1312  if (skipValuesWithinRank) {
-
1313  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1314  } else {
-
1315  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1316  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
-
1317  } else stateProb = 0;
-
1318  }
-
1319  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1320  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
-
1321  return totalStateProb;
-
1322 }
-
1323 
-
1324 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
-
1325 
-
1326  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1327 
-
1328  qreal outcomeProb;
-
1329  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1330  if (outcome == 1)
-
1331  outcomeProb = 1.0 - outcomeProb;
-
1332 
-
1333  return outcomeProb;
-
1334 }
-
1335 
-
1336 void statevec_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
-
1337 
-
1338  // each node populates retProbs with contributions from the subset of amps in each
-
1339  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
1340 
-
1341  // then, retProbs are summed element-wise
-
1342  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1343 }
+
1263  // rank's chunk is in upper half of block
+
1264  int rankIsUpper;
+
1265  int pairRank; // rank of corresponding chunk
+
1266 
+
1267  if (useLocalDataOnly){
+
1268  // all values required to update state vector lie in this rank
+
1269  statevec_hadamardLocal(qureg, targetQubit);
+
1270  } else {
+
1271  // need to get corresponding chunk of state vector from other rank
+
1272  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1273  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1274  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
1275  // get corresponding values from my pair
+
1276  exchangeStateVectors(qureg, pairRank);
+
1277  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
+
1278  // in the correct order
+
1279  if (rankIsUpper){
+ +
1281  qureg.stateVec, //upper
+
1282  qureg.pairStateVec, //lower
+
1283  qureg.stateVec, rankIsUpper); //output
+
1284  } else {
+ +
1286  qureg.pairStateVec, //upper
+
1287  qureg.stateVec, //lower
+
1288  qureg.stateVec, rankIsUpper); //output
+
1289  }
+
1290  }
+
1291 }
+
1292 
+
1303 static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
+
1304 {
+
1305  long long int sizeHalfBlock = 1LL << (measureQubit);
+
1306  int numChunksToSkip = sizeHalfBlock/chunkSize;
+
1307  // calculate probability by summing over numChunksToSkip, then skipping numChunksToSkip, etc
+
1308  int bitToCheck = chunkId & numChunksToSkip;
+
1309  return bitToCheck;
+
1310 }
+
1311 
+
1312 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
1313 {
+
1314  qreal stateProb=0, totalStateProb=0;
+
1315  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
+
1316  if (skipValuesWithinRank) {
+
1317  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
+
1318  } else {
+
1319  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
+
1320  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
+
1321  } else stateProb = 0;
+
1322  }
+
1323  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1324  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
+
1325  return totalStateProb;
+
1326 }
+
1327 
+
1328 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
+
1329 
+
1330  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
+
1331 
+
1332  qreal outcomeProb;
+
1333  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1334  if (outcome == 1)
+
1335  outcomeProb = 1.0 - outcomeProb;
+
1336 
+
1337  return outcomeProb;
+
1338 }
+
1339 
+
1340 void statevec_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
+
1341 
+
1342  // each node populates retProbs with contributions from the subset of amps in each
+
1343  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
1344 
-
1345 void densmatr_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
-
1346 
-
1347  // each node populates retProbs with contributions from the subset of amps in each
-
1348  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
1349 
-
1350  // then, retProbs are summed element-wise
-
1351  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1352 }
+
1345  // then, retProbs are summed element-wise
+
1346  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1347 }
+
1348 
+
1349 void densmatr_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
+
1350 
+
1351  // each node populates retProbs with contributions from the subset of amps in each
+
1352  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
1353 
- -
1355 
-
1356  qreal localPurity = densmatr_calcPurityLocal(qureg);
-
1357 
-
1358  qreal globalPurity;
-
1359  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1360 
-
1361  return globalPurity;
-
1362 }
-
1363 
-
1364 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
-
1365 {
-
1366  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1367  if (skipValuesWithinRank) {
-
1368  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
-
1369  } else {
-
1370  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1371  // chunk has amps for q=0
-
1372  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1373  totalStateProb);
- -
1375  } else {
-
1376  // chunk has amps for q=1
-
1377  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1378  totalStateProb);
- -
1380  }
-
1381  }
-
1382 }
-
1383 
- -
1385  // init MT random number generator with three keys -- time and pid
-
1386  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
1387  // used by the master process
-
1388 
-
1389  unsigned long int key[2];
- -
1391  // this seed will be used to generate the same random number on all procs,
-
1392  // therefore we want to make sure all procs receive the same key
-
1393  MPI_Bcast(key, 2, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
-
1394  init_by_array(key, 2);
-
1395 }
-
1396 
-
1401 long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2) {
-
1402  long long int chunkStartInd = qureg.numAmpsPerChunk * qureg.chunkId;
-
1403  long long int chunkEndInd = chunkStartInd + qureg.numAmpsPerChunk; // exclusive
-
1404  long long int oddParityInd;
-
1405 
-
1406  if (extractBit(qb1, chunkStartInd) != extractBit(qb2, chunkStartInd))
-
1407  return chunkStartInd;
-
1408 
-
1409  oddParityInd = flipBit(chunkStartInd, qb1);
-
1410  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1411  return oddParityInd;
-
1412 
-
1413  oddParityInd = flipBit(chunkStartInd, qb2);
-
1414  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
-
1415  return oddParityInd;
+
1354  // then, retProbs are summed element-wise
+
1355  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1356 }
+
1357 
+ +
1359 
+
1360  qreal localPurity = densmatr_calcPurityLocal(qureg);
+
1361 
+
1362  qreal globalPurity;
+
1363  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1364 
+
1365  return globalPurity;
+
1366 }
+
1367 
+
1368 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
+
1369 {
+
1370  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
+
1371  if (skipValuesWithinRank) {
+
1372  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
+
1373  } else {
+
1374  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
+
1375  // chunk has amps for q=0
+
1376  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
+
1377  totalStateProb);
+ +
1379  } else {
+
1380  // chunk has amps for q=1
+
1381  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
+
1382  totalStateProb);
+ +
1384  }
+
1385  }
+
1386 }
+
1387 
+
1388 void seedQuEST(QuESTEnv *env, unsigned long int* seedArray, int numSeeds) {
+
1389 
+
1390  // it is imperative every node agrees on the seed, so that random decisions
+
1391  // agree on every node. Hence we use only the master node keys.
+
1392  MPI_Bcast(seedArray, numSeeds, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
+
1393 
+
1394  // free existing seed array, if exists
+
1395  if (env->seeds != NULL)
+
1396  free(env->seeds);
+
1397 
+
1398  // record keys in permanent heap
+
1399  env->seeds = malloc(numSeeds * sizeof *(env->seeds));
+
1400  for (int i=0; i<numSeeds; i++)
+
1401  (env->seeds)[i] = seedArray[i];
+
1402  env->numSeeds = numSeeds;
+
1403 
+
1404  // pass keys to Mersenne Twister seeder
+
1405  init_by_array(seedArray, numSeeds);
+
1406 }
+
1407 
+
1412 long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2) {
+
1413  long long int chunkStartInd = qureg.numAmpsPerChunk * qureg.chunkId;
+
1414  long long int chunkEndInd = chunkStartInd + qureg.numAmpsPerChunk; // exclusive
+
1415  long long int oddParityInd;
1416 
-
1417  return -1;
-
1418 }
-
1419 
-
1420 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2) {
-
1421 
-
1422  // perform locally if possible
-
1423  int qbBig = (qb1 > qb2)? qb1 : qb2;
-
1424  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
-
1425  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
1426 
-
1427  // do nothing if this node contains no amplitudes to swap
-
1428  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
-
1429  if (oddParityGlobalInd == -1)
-
1430  return;
-
1431 
-
1432  // determine and swap amps with pair node
-
1433  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
-
1434  exchangeStateVectors(qureg, pairRank);
-
1435  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
-
1436 }
-
1437 
-
1447 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) {
-
1448  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
-
1449  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
-
1450 
-
1451  if (q1FitsInNode && q2FitsInNode) {
-
1452  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
1453 
-
1454  } else if (q1FitsInNode) {
-
1455  int qSwap = (q1 > 0)? q1-1 : q1+1;
-
1456 
-
1457  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1458  if (maskContainsBit(ctrlMask, qSwap))
-
1459  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
-
1460 
-
1461  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1462  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
-
1463  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1464 
-
1465  } else if (q2FitsInNode) {
-
1466  int qSwap = (q2 > 0)? q2-1 : q2+1;
-
1467 
+
1417  if (extractBit(qb1, chunkStartInd) != extractBit(qb2, chunkStartInd))
+
1418  return chunkStartInd;
+
1419 
+
1420  oddParityInd = flipBit(chunkStartInd, qb1);
+
1421  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
+
1422  return oddParityInd;
+
1423 
+
1424  oddParityInd = flipBit(chunkStartInd, qb2);
+
1425  if (oddParityInd >= chunkStartInd && oddParityInd < chunkEndInd)
+
1426  return oddParityInd;
+
1427 
+
1428  return -1;
+
1429 }
+
1430 
+
1431 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2) {
+
1432 
+
1433  // perform locally if possible
+
1434  int qbBig = (qb1 > qb2)? qb1 : qb2;
+
1435  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
+
1436  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
+
1437 
+
1438  // do nothing if this node contains no amplitudes to swap
+
1439  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
+
1440  if (oddParityGlobalInd == -1)
+
1441  return;
+
1442 
+
1443  // determine and swap amps with pair node
+
1444  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
+
1445  exchangeStateVectors(qureg, pairRank);
+
1446  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
+
1447 }
+
1448 
+
1458 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u) {
+
1459  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
+
1460  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
+
1461 
+
1462  if (q1FitsInNode && q2FitsInNode) {
+
1463  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
+
1464 
+
1465  } else if (q1FitsInNode) {
+
1466  int qSwap = (q1 > 0)? q1-1 : q1+1;
+
1467 
1468  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
1469  if (maskContainsBit(ctrlMask, qSwap))
-
1470  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
-
1471 
-
1472  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1473  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
-
1474  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1475 
-
1476  } else {
-
1477  // we know with certainty that both q1 and q2 >= 2
-
1478  int swap1 = 0;
-
1479  int swap2 = 1;
-
1480 
-
1481  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
-
1482  if (maskContainsBit(ctrlMask, swap1))
-
1483  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
-
1484  if (maskContainsBit(ctrlMask, swap2))
-
1485  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
+
1470  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
+
1471 
+
1472  statevec_swapQubitAmps(qureg, q2, qSwap);
+
1473  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
+
1474  statevec_swapQubitAmps(qureg, q2, qSwap);
+
1475 
+
1476  } else if (q2FitsInNode) {
+
1477  int qSwap = (q2 > 0)? q2-1 : q2+1;
+
1478 
+
1479  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
+
1480  if (maskContainsBit(ctrlMask, qSwap))
+
1481  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
+
1482 
+
1483  statevec_swapQubitAmps(qureg, q1, qSwap);
+
1484  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
+
1485  statevec_swapQubitAmps(qureg, q1, qSwap);
1486 
-
1487  statevec_swapQubitAmps(qureg, q1, swap1);
-
1488  statevec_swapQubitAmps(qureg, q2, swap2);
-
1489  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
-
1490  statevec_swapQubitAmps(qureg, q1, swap1);
-
1491  statevec_swapQubitAmps(qureg, q2, swap2);
-
1492  }
-
1493 }
-
1494 
-
1503 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u) {
-
1504 
-
1505  // bit mask of target qubits (for quick collision checking)
-
1506  long long int targMask = getQubitBitMask(targs, numTargs);
-
1507 
-
1508  // find lowest qubit available for swapping (isn't in targs)
-
1509  int freeQb=0;
-
1510  while (maskContainsBit(targMask, freeQb))
-
1511  freeQb++;
-
1512 
-
1513  // assign indices of where each target will be swapped to (else itself)
-
1514  int swapTargs[numTargs];
-
1515  for (int t=0; t<numTargs; t++) {
-
1516  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
-
1517  swapTargs[t] = targs[t];
-
1518  else {
-
1519  // mark swap
-
1520  swapTargs[t] = freeQb;
-
1521 
-
1522  // update ctrlMask if swapped-out qubit was a control
-
1523  if (maskContainsBit(ctrlMask, swapTargs[t]))
-
1524  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
-
1525 
-
1526  // locate next available on-chunk qubit
-
1527  freeQb++;
-
1528  while (maskContainsBit(targMask, freeQb))
-
1529  freeQb++;
-
1530  }
-
1531  }
-
1532 
-
1533  // perform swaps as necessary
-
1534  for (int t=0; t<numTargs; t++)
-
1535  if (swapTargs[t] != targs[t])
-
1536  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1537 
-
1538  // all target qubits have now been swapped into local memory
-
1539  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
-
1540 
-
1541  // undo swaps
-
1542  for (int t=0; t<numTargs; t++)
-
1543  if (swapTargs[t] != targs[t])
-
1544  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1545 }
-
1546 
-
1547 
- -
1549 
-
1550  /* since, for every elem in 2^N op, there is a column in 2^N x 2^N qureg,
-
1551  * we know immediately (by each node containing at least 1 element of op)
-
1552  * that every node contains at least 1 column. Hence, we know that pairStateVec
-
1553  * of qureg can fit the entirety of op.
-
1554  */
-
1555 
-
1556  // load up our local contribution
-
1557  long long int localOffset = qureg.chunkId * op.numElemsPerChunk;
-
1558  memcpy(&qureg.pairStateVec.real[localOffset], op.real, op.numElemsPerChunk * sizeof(qreal));
-
1559  memcpy(&qureg.pairStateVec.imag[localOffset], op.imag, op.numElemsPerChunk * sizeof(qreal));
-
1560 
-
1561  // work out how many messages are needed to send op chunks (2GB limit)
-
1562  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
-
1563  if (op.numElemsPerChunk < maxMsgSize)
-
1564  maxMsgSize = op.numElemsPerChunk;
-
1565  int numMsgs = op.numElemsPerChunk / maxMsgSize; // since MPI_MAX... = 2^n, division is exact
-
1566 
-
1567  // each node has a turn at broadcasting its contribution of op
-
1568  for (int broadcaster=0; broadcaster < qureg.numChunks; broadcaster++) {
-
1569  long long int broadOffset = broadcaster * op.numElemsPerChunk;
-
1570 
-
1571  // (while keeping each message smaller than MPI max)
-
1572  for (int i=0; i<numMsgs; i++) {
-
1573  MPI_Bcast(
-
1574  &qureg.pairStateVec.real[broadOffset + i*maxMsgSize],
-
1575  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1576  MPI_Bcast(
-
1577  &qureg.pairStateVec.imag[broadOffset + i*maxMsgSize],
-
1578  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
-
1579  }
-
1580  }
-
1581 }
-
1582 
- -
1584 
-
1585  copyDiagOpIntoMatrixPairState(qureg, op);
-
1586  densmatr_applyDiagonalOpLocal(qureg, op);
-
1587 }
-
1588 
- -
1590 
-
1591  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
-
1592  if (qureg.numChunks == 1)
-
1593  return localExpec;
-
1594 
-
1595  qreal localReal = localExpec.real;
-
1596  qreal localImag = localExpec.imag;
-
1597  qreal globalReal, globalImag;
-
1598  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1599  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1600 
-
1601  Complex globalExpec;
-
1602  globalExpec.real = globalReal;
-
1603  globalExpec.imag = globalImag;
-
1604  return globalExpec;
-
1605 }
-
1606 
- -
1608 
-
1609  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
1610  if (qureg.numChunks == 1)
-
1611  return localVal;
-
1612 
-
1613  qreal localRe = localVal.real;
-
1614  qreal localIm = localVal.imag;
-
1615  qreal globalRe, globalIm;
-
1616 
-
1617  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1618  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1487  } else {
+
1488  // we know with certainty that both q1 and q2 >= 2
+
1489  int swap1 = 0;
+
1490  int swap2 = 1;
+
1491 
+
1492  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
+
1493  if (maskContainsBit(ctrlMask, swap1))
+
1494  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
+
1495  if (maskContainsBit(ctrlMask, swap2))
+
1496  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
+
1497 
+
1498  statevec_swapQubitAmps(qureg, q1, swap1);
+
1499  statevec_swapQubitAmps(qureg, q2, swap2);
+
1500  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
+
1501  statevec_swapQubitAmps(qureg, q1, swap1);
+
1502  statevec_swapQubitAmps(qureg, q2, swap2);
+
1503  }
+
1504 }
+
1505 
+
1514 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u) {
+
1515 
+
1516  // bit mask of target qubits (for quick collision checking)
+
1517  long long int targMask = getQubitBitMask(targs, numTargs);
+
1518 
+
1519  // find lowest qubit available for swapping (isn't in targs)
+
1520  int freeQb=0;
+
1521  while (maskContainsBit(targMask, freeQb))
+
1522  freeQb++;
+
1523 
+
1524  // assign indices of where each target will be swapped to (else itself)
+
1525  int swapTargs[numTargs];
+
1526  for (int t=0; t<numTargs; t++) {
+
1527  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
+
1528  swapTargs[t] = targs[t];
+
1529  else {
+
1530  // mark swap
+
1531  swapTargs[t] = freeQb;
+
1532 
+
1533  // update ctrlMask if swapped-out qubit was a control
+
1534  if (maskContainsBit(ctrlMask, swapTargs[t]))
+
1535  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
+
1536 
+
1537  // locate next available on-chunk qubit
+
1538  freeQb++;
+
1539  while (maskContainsBit(targMask, freeQb))
+
1540  freeQb++;
+
1541  }
+
1542  }
+
1543 
+
1544  // perform swaps as necessary
+
1545  for (int t=0; t<numTargs; t++)
+
1546  if (swapTargs[t] != targs[t])
+
1547  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
+
1548 
+
1549  // all target qubits have now been swapped into local memory
+
1550  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
+
1551 
+
1552  // undo swaps
+
1553  for (int t=0; t<numTargs; t++)
+
1554  if (swapTargs[t] != targs[t])
+
1555  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
+
1556 }
+
1557 
+
1558 
+ +
1560 
+
1561  /* since, for every elem in 2^N op, there is a column in 2^N x 2^N qureg,
+
1562  * we know immediately (by each node containing at least 1 element of op)
+
1563  * that every node contains at least 1 column. Hence, we know that pairStateVec
+
1564  * of qureg can fit the entirety of op.
+
1565  */
+
1566 
+
1567  // load up our local contribution
+
1568  long long int localOffset = qureg.chunkId * op.numElemsPerChunk;
+
1569  memcpy(&qureg.pairStateVec.real[localOffset], op.real, op.numElemsPerChunk * sizeof(qreal));
+
1570  memcpy(&qureg.pairStateVec.imag[localOffset], op.imag, op.numElemsPerChunk * sizeof(qreal));
+
1571 
+
1572  // work out how many messages are needed to send op chunks (2GB limit)
+
1573  long long int maxMsgSize = MPI_MAX_AMPS_IN_MSG;
+
1574  if (op.numElemsPerChunk < maxMsgSize)
+
1575  maxMsgSize = op.numElemsPerChunk;
+
1576  int numMsgs = op.numElemsPerChunk / maxMsgSize; // since MPI_MAX... = 2^n, division is exact
+
1577 
+
1578  // each node has a turn at broadcasting its contribution of op
+
1579  for (int broadcaster=0; broadcaster < qureg.numChunks; broadcaster++) {
+
1580  long long int broadOffset = broadcaster * op.numElemsPerChunk;
+
1581 
+
1582  // (while keeping each message smaller than MPI max)
+
1583  for (int i=0; i<numMsgs; i++) {
+
1584  MPI_Bcast(
+
1585  &qureg.pairStateVec.real[broadOffset + i*maxMsgSize],
+
1586  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
1587  MPI_Bcast(
+
1588  &qureg.pairStateVec.imag[broadOffset + i*maxMsgSize],
+
1589  maxMsgSize, MPI_QuEST_REAL, broadcaster, MPI_COMM_WORLD);
+
1590  }
+
1591  }
+
1592 }
+
1593 
+ +
1595 
+
1596  copyDiagOpIntoMatrixPairState(qureg, op);
+
1597  densmatr_applyDiagonalOpLocal(qureg, op);
+
1598 }
+
1599 
+ +
1601 
+
1602  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
+
1603  if (qureg.numChunks == 1)
+
1604  return localExpec;
+
1605 
+
1606  qreal localReal = localExpec.real;
+
1607  qreal localImag = localExpec.imag;
+
1608  qreal globalReal, globalImag;
+
1609  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1610  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1611 
+
1612  Complex globalExpec;
+
1613  globalExpec.real = globalReal;
+
1614  globalExpec.imag = globalImag;
+
1615  return globalExpec;
+
1616 }
+
1617 
+
1619 
-
1620  Complex globalVal;
-
1621  globalVal.real = globalRe;
-
1622  globalVal.imag = globalIm;
-
1623  return globalVal;
-
1624 }
+
1620  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
+
1621  if (qureg.numChunks == 1)
+
1622  return localVal;
+
1623 
+
1624  qreal localRe = localVal.real;
+
1625  qreal localIm = localVal.imag;
+
1626  qreal globalRe, globalIm;
+
1627 
+
1628  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1629  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1630 
+
1631  Complex globalVal;
+
1632  globalVal.real = globalRe;
+
1633  globalVal.imag = globalIm;
+
1634  return globalVal;
+
1635 }
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
+
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
+
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
-
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
int rank
Definition: QuEST.h:363
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
-
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
+
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
+
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
+
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
int rank
Definition: QuEST.h:364
+
void seedQuESTDefault(QuESTEnv *env)
Seeds the random number generator with the (master node) current time and process ID.
Definition: QuEST.c:1614
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
+
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3474
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
-
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
+
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3513
+
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:230
+
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:638
+
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
+
int numSeeds
Definition: QuEST.h:367
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2503
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2437
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
+
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
+
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2542
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2476
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
Information about the environment the program is running in.
Definition: QuEST.h:361
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
+
Information about the environment the program is running in.
Definition: QuEST.h:362
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2612
-
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
+
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2651
+
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
+
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
#define qreal
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
-
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
+
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
-
qreal densmatr_calcPurity(Qureg qureg)
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3847
+
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
+
qreal densmatr_calcPurity(Qureg qureg)
+
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3887
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
qreal imag[2][2]
Definition: QuEST.h:140
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2943
-
int numRanks
Definition: QuEST.h:364
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2056
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
+
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
+
int numRanks
Definition: QuEST.h:365
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2095
qreal densmatr_calcTotalProb(Qureg qureg)
-
void exchangeStateVectors(Qureg qureg, int pairRank)
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
+
void exchangeStateVectors(Qureg qureg, int pairRank)
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2906
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
+
void statevec_pauliX(Qureg qureg, int targetQubit)
+
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2945
+
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:306
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
+
unsigned long int * seeds
Definition: QuEST.h:366
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
Represents a system of qubits.
Definition: QuEST.h:322
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
static int getChunkIdFromIndex(Qureg qureg, long long int index)
-
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2795
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2112
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2375
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
-
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
+
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
+
static int getChunkIdFromIndex(Qureg qureg, long long int index)
+
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2834
+
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
+
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2151
+
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2414
+
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
+
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
qreal real[2][2]
Definition: QuEST.h:139
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3809
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void seedQuESTDefault()
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3849
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
-
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
-
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
-
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2703
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
+
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
+
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
+
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
+
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
+
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:494
+
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
+
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2742
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
+
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3925
+
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3965
qreal imag
Definition: QuEST.h:106
-
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
+
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
+
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:547
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
qreal statevec_calcTotalProb(Qureg qureg)
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
-
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
-
void validateNumRanks(int numRanks, const char *caller)
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
+
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
+
void validateNumRanks(int numRanks, const char *caller)
+
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
+
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
Represents one complex number.
Definition: QuEST.h:103
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3100
-
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
+
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3139
+
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
static int maskContainsBit(const long long int mask, const int bitInd)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2997
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
-
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
void statevec_pauliY(Qureg qureg, int targetQubit)
+
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
+
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:3036
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
+
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
+
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal totalStateProb)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
+
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
diff --git a/docs/QuEST__cpu__internal_8h.html b/docs/QuEST__cpu__internal_8h.html index 2169f96b2..c9cf8a3a3 100644 --- a/docs/QuEST__cpu__internal_8h.html +++ b/docs/QuEST__cpu__internal_8h.html @@ -27,7 +27,7 @@ @@ -235,52 +235,52 @@

-

Definition at line 4042 of file QuEST_cpu.c.

-
4042  {
-
4043 
-
4044  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
-
4045  * Furthermore, since it's gauranteed each node contains an integer number of
-
4046  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
-
4047  * then we know iteration below begins at the 'top' of a column, and there is
-
4048  * no offset for op (pairStateVector)
-
4049  */
-
4050 
-
4051  long long int numAmps = qureg.numAmpsPerChunk;
-
4052  int opDim = (1 << op.numQubits);
-
4053 
-
4054  qreal* stateRe = qureg.stateVec.real;
-
4055  qreal* stateIm = qureg.stateVec.imag;
-
4056  qreal* opRe = qureg.pairStateVec.real;
-
4057  qreal* opIm = qureg.pairStateVec.imag;
-
4058 
-
4059  qreal a,b,c,d;
-
4060  long long int index;
-
4061 
-
4062 # ifdef _OPENMP
-
4063 # pragma omp parallel \
-
4064  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
-
4065  private (index, a,b,c,d)
-
4066 # endif
-
4067  {
-
4068 # ifdef _OPENMP
-
4069 # pragma omp for schedule (static)
-
4070 # endif
-
4071  for (index=0LL; index<numAmps; index++) {
-
4072  a = stateRe[index];
-
4073  b = stateIm[index];
-
4074  c = opRe[index % opDim];
-
4075  d = opIm[index % opDim];
-
4076 
-
4077  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
4078  stateRe[index] = a*c - b*d;
-
4079  stateIm[index] = a*d + b*c;
-
4080  }
-
4081  }
-
4082 }
+

Definition at line 4082 of file QuEST_cpu.c.

+
4082  {
+
4083 
+
4084  /* ALL values of op are pre-loaded into qureg.pairStateVector (on every node).
+
4085  * Furthermore, since it's gauranteed each node contains an integer number of
+
4086  * columns of qureg (because op upperlimits the number of nodes; 1 per element),
+
4087  * then we know iteration below begins at the 'top' of a column, and there is
+
4088  * no offset for op (pairStateVector)
+
4089  */
+
4090 
+
4091  long long int numAmps = qureg.numAmpsPerChunk;
+
4092  int opDim = (1 << op.numQubits);
+
4093 
+
4094  qreal* stateRe = qureg.stateVec.real;
+
4095  qreal* stateIm = qureg.stateVec.imag;
+
4096  qreal* opRe = qureg.pairStateVec.real;
+
4097  qreal* opIm = qureg.pairStateVec.imag;
+
4098 
+
4099  qreal a,b,c,d;
+
4100  long long int index;
+
4101 
+
4102 # ifdef _OPENMP
+
4103 # pragma omp parallel \
+
4104  shared (stateRe,stateIm, opRe,opIm, numAmps,opDim) \
+
4105  private (index, a,b,c,d)
+
4106 # endif
+
4107  {
+
4108 # ifdef _OPENMP
+
4109 # pragma omp for schedule (static)
+
4110 # endif
+
4111  for (index=0LL; index<numAmps; index++) {
+
4112  a = stateRe[index];
+
4113  b = stateIm[index];
+
4114  c = opRe[index % opDim];
+
4115  d = opIm[index % opDim];
+
4116 
+
4117  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
4118  stateRe[index] = a*c - b*d;
+
4119  stateIm[index] = a*d + b*c;
+
4120  }
+
4121  }
+
4122 }

References Qureg::numAmpsPerChunk, DiagonalOp::numQubits, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_applyDiagonalOp().

+

Referenced by densmatr_applyDiagonalOp().

@@ -310,71 +310,71 @@

-

Definition at line 4127 of file QuEST_cpu.c.

-
4127  {
-
4128 
-
4129  /* since for every 1 element in \p op, there exists a column in \p qureg,
-
4130  * we know that the elements in \p op live on the same node as the
-
4131  * corresponding diagonal elements of \p qureg. This means, the problem is
-
4132  * embarrassingly parallelisable, and the code below works for both
-
4133  * serial and distributed modes.
-
4134  */
-
4135 
-
4136  // computes first local index containing a diagonal element
-
4137  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
-
4138  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
-
4139  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
4140  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
-
4141  long long int numAmps = qureg.numAmpsPerChunk;
-
4142 
-
4143  qreal* stateReal = qureg.stateVec.real;
-
4144  qreal* stateImag = qureg.stateVec.imag;
-
4145  qreal* opReal = op.real;
-
4146  qreal* opImag = op.imag;
-
4147 
-
4148  qreal expecRe = 0;
-
4149  qreal expecIm = 0;
-
4150 
-
4151  long long int stateInd;
-
4152  long long int opInd;
-
4153  qreal matRe, matIm, opRe, opIm;
-
4154 
-
4155  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
-
4156 
-
4157 # ifdef _OPENMP
-
4158 # pragma omp parallel \
-
4159  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
-
4160  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
-
4161  reduction ( +:expecRe, expecIm )
-
4162 # endif
-
4163  {
-
4164 # ifdef _OPENMP
-
4165 # pragma omp for schedule (static)
-
4166 # endif
-
4167  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
-
4168 
-
4169  matRe = stateReal[stateInd];
-
4170  matIm = stateImag[stateInd];
-
4171  opInd = (stateInd - localIndNextDiag) / diagSpacing;
-
4172  opRe = opReal[opInd];
-
4173  opIm = opImag[opInd];
-
4174 
-
4175  // (matRe + matIm i)(opRe + opIm i) =
-
4176  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
4177  expecRe += matRe * opRe - matIm * opIm;
-
4178  expecIm += matRe * opIm + matIm * opRe;
-
4179  }
-
4180  }
-
4181 
-
4182  Complex expecVal;
-
4183  expecVal.real = expecRe;
-
4184  expecVal.imag = expecIm;
-
4185  return expecVal;
-
4186 }
+

Definition at line 4167 of file QuEST_cpu.c.

+
4167  {
+
4168 
+
4169  /* since for every 1 element in \p op, there exists a column in \p qureg,
+
4170  * we know that the elements in \p op live on the same node as the
+
4171  * corresponding diagonal elements of \p qureg. This means, the problem is
+
4172  * embarrassingly parallelisable, and the code below works for both
+
4173  * serial and distributed modes.
+
4174  */
+
4175 
+
4176  // computes first local index containing a diagonal element
+
4177  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
+
4178  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
+
4179  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
4180  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
+
4181  long long int numAmps = qureg.numAmpsPerChunk;
+
4182 
+
4183  qreal* stateReal = qureg.stateVec.real;
+
4184  qreal* stateImag = qureg.stateVec.imag;
+
4185  qreal* opReal = op.real;
+
4186  qreal* opImag = op.imag;
+
4187 
+
4188  qreal expecRe = 0;
+
4189  qreal expecIm = 0;
+
4190 
+
4191  long long int stateInd;
+
4192  long long int opInd;
+
4193  qreal matRe, matIm, opRe, opIm;
+
4194 
+
4195  // visits every diagonal element with global index (2^n + 1)i for i in [0, 2^n-1]
+
4196 
+
4197 # ifdef _OPENMP
+
4198 # pragma omp parallel \
+
4199  shared (stateReal,stateImag, opReal,opImag, localIndNextDiag,diagSpacing,numAmps) \
+
4200  private (stateInd,opInd, matRe,matIm, opRe,opIm) \
+
4201  reduction ( +:expecRe, expecIm )
+
4202 # endif
+
4203  {
+
4204 # ifdef _OPENMP
+
4205 # pragma omp for schedule (static)
+
4206 # endif
+
4207  for (stateInd=localIndNextDiag; stateInd < numAmps; stateInd += diagSpacing) {
+
4208 
+
4209  matRe = stateReal[stateInd];
+
4210  matIm = stateImag[stateInd];
+
4211  opInd = (stateInd - localIndNextDiag) / diagSpacing;
+
4212  opRe = opReal[opInd];
+
4213  opIm = opImag[opInd];
+
4214 
+
4215  // (matRe + matIm i)(opRe + opIm i) =
+
4216  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
+
4217  expecRe += matRe * opRe - matIm * opIm;
+
4218  expecIm += matRe * opIm + matIm * opRe;
+
4219  }
+
4220  }
+
4221 
+
4222  Complex expecVal;
+
4223  expecVal.real = expecRe;
+
4224  expecVal.imag = expecIm;
+
4225  return expecVal;
+
4226 }

References Qureg::chunkId, Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

-

Referenced by densmatr_calcExpecDiagonalOp().

+

Referenced by densmatr_calcExpecDiagonalOp().

@@ -406,91 +406,91 @@

Definition at line 990 of file QuEST_cpu.c.

-
990  {
-
991 
-
992  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
-
993  * We only consult the attributes.
-
994  *
-
995  * qureg is a density matrix, and pureState is a statevector.
-
996  * Every node contains as many columns of qureg as amps by pureState.
-
997  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
-
998  * Ergo, this node contains columns:
-
999  * qureg.chunkID * pureState.numAmpsPerChunk to
-
1000  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
-
1001  *
-
1002  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
-
1003  * entire pureState state-vector
-
1004  */
-
1005 
-
1006  // unpack everything for OPENMP
-
1007  qreal* vecRe = qureg.pairStateVec.real;
-
1008  qreal* vecIm = qureg.pairStateVec.imag;
-
1009  qreal* densRe = qureg.stateVec.real;
-
1010  qreal* densIm = qureg.stateVec.imag;
-
1011 
-
1012  int row, col;
-
1013  int dim = (int) pureState.numAmpsTotal;
-
1014  int colsPerNode = (int) pureState.numAmpsPerChunk;
-
1015  // using only int, because density matrix has squared as many amps so its
-
1016  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
-
1017 
-
1018  // starting GLOBAL column index of the qureg columns on this node
-
1019  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
-
1020 
-
1021  qreal densElemRe, densElemIm;
-
1022  qreal prefacRe, prefacIm;
-
1023  qreal rowSumRe, rowSumIm;
-
1024  qreal vecElemRe, vecElemIm;
-
1025 
-
1026  // quantity computed by this node
-
1027  qreal globalSumRe = 0; // imag-component is assumed zero
+

Definition at line 1001 of file QuEST_cpu.c.

+
1001  {
+
1002 
+
1003  /* Here, elements of pureState are not accessed (instead grabbed from qureg.pair).
+
1004  * We only consult the attributes.
+
1005  *
+
1006  * qureg is a density matrix, and pureState is a statevector.
+
1007  * Every node contains as many columns of qureg as amps by pureState.
+
1008  * (each node contains an integer, exponent-of-2 number of whole columns of qureg)
+
1009  * Ergo, this node contains columns:
+
1010  * qureg.chunkID * pureState.numAmpsPerChunk to
+
1011  * (qureg.chunkID + 1) * pureState.numAmpsPerChunk
+
1012  *
+
1013  * The first pureState.numAmpsTotal elements of qureg.pairStateVec are the
+
1014  * entire pureState state-vector
+
1015  */
+
1016 
+
1017  // unpack everything for OPENMP
+
1018  qreal* vecRe = qureg.pairStateVec.real;
+
1019  qreal* vecIm = qureg.pairStateVec.imag;
+
1020  qreal* densRe = qureg.stateVec.real;
+
1021  qreal* densIm = qureg.stateVec.imag;
+
1022 
+
1023  int row, col;
+
1024  int dim = (int) pureState.numAmpsTotal;
+
1025  int colsPerNode = (int) pureState.numAmpsPerChunk;
+
1026  // using only int, because density matrix has squared as many amps so its
+
1027  // iteration would be impossible if the pureStates numAmpsTotal didn't fit into int
1028 
-
1029 # ifdef _OPENMP
-
1030 # pragma omp parallel \
-
1031  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
-
1032  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
-
1033  reduction ( +:globalSumRe )
-
1034 # endif
-
1035  {
-
1036 # ifdef _OPENMP
-
1037 # pragma omp for schedule (static)
-
1038 # endif
-
1039  // indices of my GLOBAL row
-
1040  for (row=0; row < dim; row++) {
-
1041 
-
1042  // single element of conj(pureState)
-
1043  prefacRe = vecRe[row];
-
1044  prefacIm = - vecIm[row];
-
1045 
-
1046  rowSumRe = 0;
-
1047  rowSumIm = 0;
-
1048 
-
1049  // indices of my LOCAL column
-
1050  for (col=0; col < colsPerNode; col++) {
-
1051 
-
1052  // my local density element
-
1053  densElemRe = densRe[row + dim*col];
-
1054  densElemIm = densIm[row + dim*col];
-
1055 
-
1056  // state-vector element
-
1057  vecElemRe = vecRe[startCol + col];
-
1058  vecElemIm = vecIm[startCol + col];
+
1029  // starting GLOBAL column index of the qureg columns on this node
+
1030  int startCol = (int) (qureg.chunkId * pureState.numAmpsPerChunk);
+
1031 
+
1032  qreal densElemRe, densElemIm;
+
1033  qreal prefacRe, prefacIm;
+
1034  qreal rowSumRe, rowSumIm;
+
1035  qreal vecElemRe, vecElemIm;
+
1036 
+
1037  // quantity computed by this node
+
1038  qreal globalSumRe = 0; // imag-component is assumed zero
+
1039 
+
1040 # ifdef _OPENMP
+
1041 # pragma omp parallel \
+
1042  shared (vecRe,vecIm,densRe,densIm, dim,colsPerNode,startCol) \
+
1043  private (row,col, prefacRe,prefacIm, rowSumRe,rowSumIm, densElemRe,densElemIm, vecElemRe,vecElemIm) \
+
1044  reduction ( +:globalSumRe )
+
1045 # endif
+
1046  {
+
1047 # ifdef _OPENMP
+
1048 # pragma omp for schedule (static)
+
1049 # endif
+
1050  // indices of my GLOBAL row
+
1051  for (row=0; row < dim; row++) {
+
1052 
+
1053  // single element of conj(pureState)
+
1054  prefacRe = vecRe[row];
+
1055  prefacIm = - vecIm[row];
+
1056 
+
1057  rowSumRe = 0;
+
1058  rowSumIm = 0;
1059 
-
1060  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
-
1061  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
-
1062  }
-
1063 
-
1064  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
-
1065  }
-
1066  }
-
1067 
-
1068  return globalSumRe;
-
1069 }
+
1060  // indices of my LOCAL column
+
1061  for (col=0; col < colsPerNode; col++) {
+
1062 
+
1063  // my local density element
+
1064  densElemRe = densRe[row + dim*col];
+
1065  densElemIm = densIm[row + dim*col];
+
1066 
+
1067  // state-vector element
+
1068  vecElemRe = vecRe[startCol + col];
+
1069  vecElemIm = vecIm[startCol + col];
+
1070 
+
1071  rowSumRe += densElemRe*vecElemRe - densElemIm*vecElemIm;
+
1072  rowSumIm += densElemRe*vecElemIm + densElemIm*vecElemRe;
+
1073  }
+
1074 
+
1075  globalSumRe += rowSumRe*prefacRe - rowSumIm*prefacIm;
+
1076  }
+
1077  }
+
1078 
+
1079  return globalSumRe;
+
1080 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcFidelity().

+

Referenced by densmatr_calcFidelity().

@@ -522,44 +522,44 @@

Definition at line 923 of file QuEST_cpu.c.

-
923  {
-
924 
-
925  long long int index;
-
926  long long int numAmps = a.numAmpsPerChunk;
-
927 
-
928  qreal *aRe = a.stateVec.real;
-
929  qreal *aIm = a.stateVec.imag;
-
930  qreal *bRe = b.stateVec.real;
-
931  qreal *bIm = b.stateVec.imag;
-
932 
-
933  qreal trace = 0;
-
934  qreal difRe, difIm;
+

Definition at line 934 of file QuEST_cpu.c.

+
934  {
935 
-
936 # ifdef _OPENMP
-
937 # pragma omp parallel \
-
938  shared (aRe,aIm, bRe,bIm, numAmps) \
-
939  private (index,difRe,difIm) \
-
940  reduction ( +:trace )
-
941 # endif
-
942  {
-
943 # ifdef _OPENMP
-
944 # pragma omp for schedule (static)
-
945 # endif
-
946  for (index=0LL; index<numAmps; index++) {
-
947 
-
948  difRe = aRe[index] - bRe[index];
-
949  difIm = aIm[index] - bIm[index];
-
950  trace += difRe*difRe + difIm*difIm;
-
951  }
-
952  }
-
953 
-
954  return trace;
-
955 }
+
936  long long int index;
+
937  long long int numAmps = a.numAmpsPerChunk;
+
938 
+
939  qreal *aRe = a.stateVec.real;
+
940  qreal *aIm = a.stateVec.imag;
+
941  qreal *bRe = b.stateVec.real;
+
942  qreal *bIm = b.stateVec.imag;
+
943 
+
944  qreal trace = 0;
+
945  qreal difRe, difIm;
+
946 
+
947 # ifdef _OPENMP
+
948 # pragma omp parallel \
+
949  shared (aRe,aIm, bRe,bIm, numAmps) \
+
950  private (index,difRe,difIm) \
+
951  reduction ( +:trace )
+
952 # endif
+
953  {
+
954 # ifdef _OPENMP
+
955 # pragma omp for schedule (static)
+
956 # endif
+
957  for (index=0LL; index<numAmps; index++) {
+
958 
+
959  difRe = aRe[index] - bRe[index];
+
960  difIm = aIm[index] - bIm[index];
+
961  trace += difRe*difRe + difIm*difIm;
+
962  }
+
963  }
+
964 
+
965  return trace;
+
966 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcHilbertSchmidtDistance().

+

Referenced by densmatr_calcHilbertSchmidtDistance().

@@ -591,40 +591,40 @@

Definition at line 958 of file QuEST_cpu.c.

-
958  {
-
959 
-
960  long long int index;
-
961  long long int numAmps = a.numAmpsPerChunk;
-
962 
-
963  qreal *aRe = a.stateVec.real;
-
964  qreal *aIm = a.stateVec.imag;
-
965  qreal *bRe = b.stateVec.real;
-
966  qreal *bIm = b.stateVec.imag;
-
967 
-
968  qreal trace = 0;
-
969 
-
970 # ifdef _OPENMP
-
971 # pragma omp parallel \
-
972  shared (aRe,aIm, bRe,bIm, numAmps) \
-
973  private (index) \
-
974  reduction ( +:trace )
-
975 # endif
-
976  {
-
977 # ifdef _OPENMP
-
978 # pragma omp for schedule (static)
-
979 # endif
-
980  for (index=0LL; index<numAmps; index++) {
-
981  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
-
982  }
-
983  }
-
984 
-
985  return trace;
-
986 }
+

Definition at line 969 of file QuEST_cpu.c.

+
969  {
+
970 
+
971  long long int index;
+
972  long long int numAmps = a.numAmpsPerChunk;
+
973 
+
974  qreal *aRe = a.stateVec.real;
+
975  qreal *aIm = a.stateVec.imag;
+
976  qreal *bRe = b.stateVec.real;
+
977  qreal *bIm = b.stateVec.imag;
+
978 
+
979  qreal trace = 0;
+
980 
+
981 # ifdef _OPENMP
+
982 # pragma omp parallel \
+
983  shared (aRe,aIm, bRe,bIm, numAmps) \
+
984  private (index) \
+
985  reduction ( +:trace )
+
986 # endif
+
987  {
+
988 # ifdef _OPENMP
+
989 # pragma omp for schedule (static)
+
990 # endif
+
991  for (index=0LL; index<numAmps; index++) {
+
992  trace += aRe[index]*bRe[index] + aIm[index]*bIm[index];
+
993  }
+
994  }
+
995 
+
996  return trace;
+
997 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcInnerProduct().

+

Referenced by densmatr_calcInnerProduct().

@@ -666,81 +666,81 @@

-

Definition at line 3576 of file QuEST_cpu.c.

-
3576  {
-
3577 
-
3578  // clear outcomeProbs (in parallel, in case it's large)
-
3579  long long int numOutcomeProbs = (1 << numQubits);
-
3580  long long int j;
-
3581 
-
3582 # ifdef _OPENMP
-
3583 # pragma omp parallel \
-
3584  default (none) \
-
3585  shared (numOutcomeProbs,outcomeProbs) \
-
3586  private (j)
-
3587 # endif
-
3588  {
-
3589 # ifdef _OPENMP
-
3590 # pragma omp for schedule (static)
-
3591 # endif
-
3592  for (j=0; j<numOutcomeProbs; j++)
-
3593  outcomeProbs[j] = 0;
-
3594  }
-
3595 
-
3596  // compute first local index containing a diagonal element
-
3597  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3598  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3599  long long int diagSpacing = 1LL + densityDim;
-
3600  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3601  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3602  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3603  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3604 
-
3605  // computes how many diagonals are contained in this chunk
-
3606  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3607  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3608  numDiagsInThisChunk -= 1;
-
3609 
-
3610  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3611  long long int basisStateInd; // current diagonal index being considered
-
3612  long long int index; // index in the local chunk
-
3613 
-
3614  int q;
-
3615  long long int outcomeInd;
-
3616  qreal *stateRe = qureg.stateVec.real;
+

Definition at line 3616 of file QuEST_cpu.c.

+
3616  {
3617 
-
3618 # ifdef _OPENMP
-
3619 # pragma omp parallel \
-
3620  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateRe, numDiagsInThisChunk, qubits,numQubits, outcomeProbs) \
-
3621  private (visitedDiags, basisStateInd, index, q,outcomeInd)
-
3622 # endif
-
3623  {
-
3624 # ifdef _OPENMP
-
3625 # pragma omp for schedule (static)
-
3626 # endif
-
3627  // sums the diagonal elems of the density matrix where measureQubit=0
-
3628  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3629 
-
3630  basisStateInd = numPrevDiags + visitedDiags;
-
3631  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3632 
-
3633  // determine outcome implied by basisStateInd
-
3634  outcomeInd = 0;
-
3635  for (q=0; q<numQubits; q++)
-
3636  outcomeInd += extractBit(qubits[q], basisStateInd) * (1LL << q);
-
3637 
-
3638  // atomicly update corresponding outcome array element
-
3639  # ifdef _OPENMP
-
3640  # pragma omp atomic update
-
3641  # endif
-
3642  outcomeProbs[outcomeInd] += stateRe[index];
-
3643  }
-
3644  }
-
3645 }
+
3618  // clear outcomeProbs (in parallel, in case it's large)
+
3619  long long int numOutcomeProbs = (1 << numQubits);
+
3620  long long int j;
+
3621 
+
3622 # ifdef _OPENMP
+
3623 # pragma omp parallel \
+
3624  default (none) \
+
3625  shared (numOutcomeProbs,outcomeProbs) \
+
3626  private (j)
+
3627 # endif
+
3628  {
+
3629 # ifdef _OPENMP
+
3630 # pragma omp for schedule (static)
+
3631 # endif
+
3632  for (j=0; j<numOutcomeProbs; j++)
+
3633  outcomeProbs[j] = 0;
+
3634  }
+
3635 
+
3636  // compute first local index containing a diagonal element
+
3637  long long int localNumAmps = qureg.numAmpsPerChunk;
+
3638  long long int densityDim = (1LL << qureg.numQubitsRepresented);
+
3639  long long int diagSpacing = 1LL + densityDim;
+
3640  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
+
3641  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
+
3642  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
3643  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
+
3644 
+
3645  // computes how many diagonals are contained in this chunk
+
3646  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
+
3647  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
+
3648  numDiagsInThisChunk -= 1;
+
3649 
+
3650  long long int visitedDiags; // number of visited diagonals in this chunk so far
+
3651  long long int basisStateInd; // current diagonal index being considered
+
3652  long long int index; // index in the local chunk
+
3653 
+
3654  int q;
+
3655  long long int outcomeInd;
+
3656  qreal *stateRe = qureg.stateVec.real;
+
3657 
+
3658 # ifdef _OPENMP
+
3659 # pragma omp parallel \
+
3660  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateRe, numDiagsInThisChunk, qubits,numQubits, outcomeProbs) \
+
3661  private (visitedDiags, basisStateInd, index, q,outcomeInd)
+
3662 # endif
+
3663  {
+
3664 # ifdef _OPENMP
+
3665 # pragma omp for schedule (static)
+
3666 # endif
+
3667  // sums the diagonal elems of the density matrix where measureQubit=0
+
3668  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
+
3669 
+
3670  basisStateInd = numPrevDiags + visitedDiags;
+
3671  index = localIndNextDiag + diagSpacing * visitedDiags;
+
3672 
+
3673  // determine outcome implied by basisStateInd
+
3674  outcomeInd = 0;
+
3675  for (q=0; q<numQubits; q++)
+
3676  outcomeInd += extractBit(qubits[q], basisStateInd) * (1LL << q);
+
3677 
+
3678  // atomicly update corresponding outcome array element
+
3679  # ifdef _OPENMP
+
3680  # pragma omp atomic
+
3681  # endif
+
3682  outcomeProbs[outcomeInd] += stateRe[index];
+
3683  }
+
3684  }
+
3685 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcProbOfAllOutcomes().

+

Referenced by densmatr_calcProbOfAllOutcomes().

@@ -760,39 +760,39 @@

-

Definition at line 861 of file QuEST_cpu.c.

-
861  {
-
862 
-
863  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
-
864  long long int index;
-
865  long long int numAmps = qureg.numAmpsPerChunk;
-
866 
-
867  qreal trace = 0;
-
868  qreal *vecRe = qureg.stateVec.real;
-
869  qreal *vecIm = qureg.stateVec.imag;
-
870 
-
871 # ifdef _OPENMP
-
872 # pragma omp parallel \
-
873  shared (vecRe, vecIm, numAmps) \
-
874  private (index) \
-
875  reduction ( +:trace )
-
876 # endif
-
877  {
-
878 # ifdef _OPENMP
-
879 # pragma omp for schedule (static)
-
880 # endif
-
881  for (index=0LL; index<numAmps; index++) {
-
882 
-
883  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
-
884  }
-
885  }
-
886 
-
887  return trace;
-
888 }
+

Definition at line 872 of file QuEST_cpu.c.

+
872  {
+
873 
+
874  /* sum of qureg^2, which is sum_i |qureg[i]|^2 */
+
875  long long int index;
+
876  long long int numAmps = qureg.numAmpsPerChunk;
+
877 
+
878  qreal trace = 0;
+
879  qreal *vecRe = qureg.stateVec.real;
+
880  qreal *vecIm = qureg.stateVec.imag;
+
881 
+
882 # ifdef _OPENMP
+
883 # pragma omp parallel \
+
884  shared (vecRe, vecIm, numAmps) \
+
885  private (index) \
+
886  reduction ( +:trace )
+
887 # endif
+
888  {
+
889 # ifdef _OPENMP
+
890 # pragma omp for schedule (static)
+
891 # endif
+
892  for (index=0LL; index<numAmps; index++) {
+
893 
+
894  trace += vecRe[index]*vecRe[index] + vecIm[index]*vecIm[index];
+
895  }
+
896  }
+
897 
+
898  return trace;
+
899 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcPurity().

+

Referenced by densmatr_calcPurity().

@@ -822,58 +822,58 @@

-

Definition at line 3363 of file QuEST_cpu.c.

-
3363  {
-
3364 
-
3365  // computes first local index containing a diagonal element
-
3366  long long int localNumAmps = qureg.numAmpsPerChunk;
-
3367  long long int densityDim = (1LL << qureg.numQubitsRepresented);
-
3368  long long int diagSpacing = 1LL + densityDim;
-
3369  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
-
3370  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
-
3371  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
-
3372  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
-
3373 
-
3374  // computes how many diagonals are contained in this chunk
-
3375  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
-
3376  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
-
3377  numDiagsInThisChunk -= 1;
-
3378 
-
3379  long long int visitedDiags; // number of visited diagonals in this chunk so far
-
3380  long long int basisStateInd; // current diagonal index being considered
-
3381  long long int index; // index in the local chunk
-
3382 
-
3383  qreal zeroProb = 0;
-
3384  qreal *stateVecReal = qureg.stateVec.real;
-
3385 
-
3386 # ifdef _OPENMP
-
3387 # pragma omp parallel \
-
3388  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
-
3389  private (visitedDiags, basisStateInd, index) \
-
3390  reduction ( +:zeroProb )
-
3391 # endif
-
3392  {
-
3393 # ifdef _OPENMP
-
3394 # pragma omp for schedule (static)
-
3395 # endif
-
3396  // sums the diagonal elems of the density matrix where measureQubit=0
-
3397  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
-
3398 
-
3399  basisStateInd = numPrevDiags + visitedDiags;
-
3400  index = localIndNextDiag + diagSpacing * visitedDiags;
-
3401 
-
3402  if (extractBit(measureQubit, basisStateInd) == 0)
-
3403  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
-
3404 
-
3405  }
-
3406  }
-
3407 
-
3408  return zeroProb;
-
3409 }
+

Definition at line 3402 of file QuEST_cpu.c.

+
3402  {
+
3403 
+
3404  // computes first local index containing a diagonal element
+
3405  long long int localNumAmps = qureg.numAmpsPerChunk;
+
3406  long long int densityDim = (1LL << qureg.numQubitsRepresented);
+
3407  long long int diagSpacing = 1LL + densityDim;
+
3408  long long int maxNumDiagsPerChunk = 1 + localNumAmps / diagSpacing;
+
3409  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*localNumAmps)/diagSpacing : 0;
+
3410  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
+
3411  long long int localIndNextDiag = globalIndNextDiag % localNumAmps;
+
3412 
+
3413  // computes how many diagonals are contained in this chunk
+
3414  long long int numDiagsInThisChunk = maxNumDiagsPerChunk;
+
3415  if (localIndNextDiag + (numDiagsInThisChunk-1)*diagSpacing >= localNumAmps)
+
3416  numDiagsInThisChunk -= 1;
+
3417 
+
3418  long long int visitedDiags; // number of visited diagonals in this chunk so far
+
3419  long long int basisStateInd; // current diagonal index being considered
+
3420  long long int index; // index in the local chunk
+
3421 
+
3422  qreal zeroProb = 0;
+
3423  qreal *stateVecReal = qureg.stateVec.real;
+
3424 
+
3425 # ifdef _OPENMP
+
3426 # pragma omp parallel \
+
3427  shared (localIndNextDiag, numPrevDiags, diagSpacing, stateVecReal, numDiagsInThisChunk) \
+
3428  private (visitedDiags, basisStateInd, index) \
+
3429  reduction ( +:zeroProb )
+
3430 # endif
+
3431  {
+
3432 # ifdef _OPENMP
+
3433 # pragma omp for schedule (static)
+
3434 # endif
+
3435  // sums the diagonal elems of the density matrix where measureQubit=0
+
3436  for (visitedDiags = 0; visitedDiags < numDiagsInThisChunk; visitedDiags++) {
+
3437 
+
3438  basisStateInd = numPrevDiags + visitedDiags;
+
3439  index = localIndNextDiag + diagSpacing * visitedDiags;
+
3440 
+
3441  if (extractBit(measureQubit, basisStateInd) == 0)
+
3442  zeroProb += stateVecReal[index]; // assume imag[diagonls] ~ 0
+
3443 
+
3444  }
+
3445  }
+
3446 
+
3447  return zeroProb;
+
3448 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_calcProbOfOutcome().

+

Referenced by densmatr_calcProbOfOutcome().

@@ -903,63 +903,63 @@

-

Definition at line 1184 of file QuEST_cpu.c.

-
1184  {
-
1185 
-
1186  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
-
1187  * which contains the full pure statevector.
-
1188  * targetQureg has as many columns on node as copyQureg has amps
-
1189  */
-
1190 
-
1191  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
-
1192  long long int colsPerNode = copyQureg.numAmpsPerChunk;
-
1193  long long int rowsPerNode = copyQureg.numAmpsTotal;
-
1194 
-
1195  // unpack vars for OpenMP
-
1196  qreal* vecRe = targetQureg.pairStateVec.real;
-
1197  qreal* vecIm = targetQureg.pairStateVec.imag;
-
1198  qreal* densRe = targetQureg.stateVec.real;
-
1199  qreal* densIm = targetQureg.stateVec.imag;
-
1200 
-
1201  long long int col, row, index;
-
1202 
-
1203  // a_i conj(a_j) |i><j|
-
1204  qreal ketRe, ketIm, braRe, braIm;
+

Definition at line 1195 of file QuEST_cpu.c.

+
1195  {
+
1196 
+
1197  /* copyQureg amps aren't explicitly used - they're accessed through targetQureg.pair,
+
1198  * which contains the full pure statevector.
+
1199  * targetQureg has as many columns on node as copyQureg has amps
+
1200  */
+
1201 
+
1202  long long int colOffset = targetQureg.chunkId * copyQureg.numAmpsPerChunk;
+
1203  long long int colsPerNode = copyQureg.numAmpsPerChunk;
+
1204  long long int rowsPerNode = copyQureg.numAmpsTotal;
1205 
-
1206 # ifdef _OPENMP
-
1207 # pragma omp parallel \
-
1208  default (none) \
-
1209  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
-
1210  private (col,row, ketRe,ketIm,braRe,braIm, index)
-
1211 # endif
-
1212  {
-
1213 # ifdef _OPENMP
-
1214 # pragma omp for schedule (static)
-
1215 # endif
-
1216  // local column
-
1217  for (col=0; col < colsPerNode; col++) {
-
1218 
-
1219  // global row
-
1220  for (row=0; row < rowsPerNode; row++) {
-
1221 
-
1222  // get pure state amps
-
1223  ketRe = vecRe[row];
-
1224  ketIm = vecIm[row];
-
1225  braRe = vecRe[col + colOffset];
-
1226  braIm = - vecIm[col + colOffset]; // minus for conjugation
-
1227 
-
1228  // update density matrix
-
1229  index = row + col*rowsPerNode; // local ind
-
1230  densRe[index] = ketRe*braRe - ketIm*braIm;
-
1231  densIm[index] = ketRe*braIm + ketIm*braRe;
-
1232  }
-
1233  }
-
1234  }
-
1235 }
+
1206  // unpack vars for OpenMP
+
1207  qreal* vecRe = targetQureg.pairStateVec.real;
+
1208  qreal* vecIm = targetQureg.pairStateVec.imag;
+
1209  qreal* densRe = targetQureg.stateVec.real;
+
1210  qreal* densIm = targetQureg.stateVec.imag;
+
1211 
+
1212  long long int col, row, index;
+
1213 
+
1214  // a_i conj(a_j) |i><j|
+
1215  qreal ketRe, ketIm, braRe, braIm;
+
1216 
+
1217 # ifdef _OPENMP
+
1218 # pragma omp parallel \
+
1219  default (none) \
+
1220  shared (colOffset, colsPerNode,rowsPerNode, vecRe,vecIm,densRe,densIm) \
+
1221  private (col,row, ketRe,ketIm,braRe,braIm, index)
+
1222 # endif
+
1223  {
+
1224 # ifdef _OPENMP
+
1225 # pragma omp for schedule (static)
+
1226 # endif
+
1227  // local column
+
1228  for (col=0; col < colsPerNode; col++) {
+
1229 
+
1230  // global row
+
1231  for (row=0; row < rowsPerNode; row++) {
+
1232 
+
1233  // get pure state amps
+
1234  ketRe = vecRe[row];
+
1235  ketIm = vecIm[row];
+
1236  braRe = vecRe[col + colOffset];
+
1237  braIm = - vecIm[col + colOffset]; // minus for conjugation
+
1238 
+
1239  // update density matrix
+
1240  index = row + col*rowsPerNode; // local ind
+
1241  densRe[index] = ketRe*braRe - ketIm*braIm;
+
1242  densIm[index] = ketRe*braIm + ketIm*braRe;
+
1243  }
+
1244  }
+
1245  }
+
1246 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_initPureState().

+

Referenced by densmatr_initPureState().

@@ -995,97 +995,97 @@

-

Definition at line 300 of file QuEST_cpu.c.

-
300  {
-
301  qreal retain=1-damping;
-
302  qreal dephase=sqrt(1-damping);
-
303 
-
304  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
-
305  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
306 
-
307  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
-
308 
-
309  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
310  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
311  long long int thisInnerBlock, // current block
-
312  thisOuterColumn, // current column in density matrix
-
313  thisIndex, // current index in (density matrix representation) state vector
-
314  thisIndexInOuterColumn,
-
315  thisIndexInInnerBlock;
-
316  int outerBit;
-
317  int stateBit;
-
318 
-
319  long long int thisTask;
-
320  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
321 
-
322  // set dimensions
-
323  sizeInnerHalfBlock = 1LL << targetQubit;
-
324  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
325  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
326  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+

Definition at line 306 of file QuEST_cpu.c.

+
306  {
+
307  qreal retain=1-damping;
+
308  qreal dephase=sqrt(1-damping);
+
309 
+
310  // multiply the off-diagonal (|0><1| and |1><0|) terms by sqrt(1-damping)
+
311  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
+
312 
+
313  // below, we modify the diagonals terms which require |1><1| to |0><0| communication
+
314 
+
315  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
316  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
317  long long int thisInnerBlock, // current block
+
318  thisOuterColumn, // current column in density matrix
+
319  thisIndex, // current index in (density matrix representation) state vector
+
320  thisIndexInOuterColumn,
+
321  thisIndexInInnerBlock;
+
322  int outerBit;
+
323  int stateBit;
+
324 
+
325  long long int thisTask;
+
326  long long int numTasks=qureg.numAmpsPerChunk>>1;
327 
-
328 # ifdef _OPENMP
-
329 # pragma omp parallel \
-
330  default (none) \
-
331  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
332  qureg,damping, retain, dephase, numTasks,targetQubit) \
-
333  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
334  thisIndexInInnerBlock,outerBit, stateBit)
-
335 # endif
-
336  {
-
337 # ifdef _OPENMP
-
338 # pragma omp for schedule (static)
-
339 # endif
-
340  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
341  // treat this as iterating over all columns, then iterating over half the values
-
342  // within one column.
-
343  // If this function has been called, this process' chunk contains half an
-
344  // outer block or less
-
345  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
346  // we want to process all columns in the density matrix,
-
347  // updating the values for half of each column (one half of each inner block)
-
348  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
349  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
350  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
351  // get index in state vector corresponding to upper inner block
-
352  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
353  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
354  + thisIndexInInnerBlock;
-
355  // check if we are in the upper or lower half of an outer block
-
356  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
357  // if we are in the lower half of an outer block, shift to be in the lower half
-
358  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
359  thisIndex += outerBit*(sizeInnerHalfBlock);
-
360 
-
361  // NOTE: at this point thisIndex should be the index of the element we want to
-
362  // dephase in the chunk of the state vector on this process, in the
-
363  // density matrix representation.
-
364  // thisTask is the index of the pair element in pairStateVec
-
365 
-
366  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
-
367  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
-
368  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
-
369 
-
370  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
371  // + pair[thisTask])/2
-
372  if(stateBit == 0){
-
373  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
-
374  damping*( qureg.pairStateVec.real[thisTask]);
-
375 
-
376  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
-
377  damping*( qureg.pairStateVec.imag[thisTask]);
-
378  } else{
-
379  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
-
380 
-
381  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
-
382  }
-
383  }
-
384  }
-
385 }
+
328  // set dimensions
+
329  sizeInnerHalfBlock = 1LL << targetQubit;
+
330  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
331  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
332  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
333 
+
334 # ifdef _OPENMP
+
335 # pragma omp parallel \
+
336  default (none) \
+
337  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
338  qureg,damping, retain, dephase, numTasks,targetQubit) \
+
339  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
340  thisIndexInInnerBlock,outerBit, stateBit)
+
341 # endif
+
342  {
+
343 # ifdef _OPENMP
+
344 # pragma omp for schedule (static)
+
345 # endif
+
346  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
347  // treat this as iterating over all columns, then iterating over half the values
+
348  // within one column.
+
349  // If this function has been called, this process' chunk contains half an
+
350  // outer block or less
+
351  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
352  // we want to process all columns in the density matrix,
+
353  // updating the values for half of each column (one half of each inner block)
+
354  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
355  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
356  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
357  // get index in state vector corresponding to upper inner block
+
358  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
359  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
360  + thisIndexInInnerBlock;
+
361  // check if we are in the upper or lower half of an outer block
+
362  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
363  // if we are in the lower half of an outer block, shift to be in the lower half
+
364  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
365  thisIndex += outerBit*(sizeInnerHalfBlock);
+
366 
+
367  // NOTE: at this point thisIndex should be the index of the element we want to
+
368  // dephase in the chunk of the state vector on this process, in the
+
369  // density matrix representation.
+
370  // thisTask is the index of the pair element in pairStateVec
+
371 
+
372  // Extract state bit, is 0 if thisIndex corresponds to a state with 0 in the target qubit
+
373  // and is 1 if thisIndex corresponds to a state with 1 in the target qubit
+
374  stateBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId));
+
375 
+
376  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
377  // + pair[thisTask])/2
+
378  if(stateBit == 0){
+
379  qureg.stateVec.real[thisIndex] = qureg.stateVec.real[thisIndex] +
+
380  damping*( qureg.pairStateVec.real[thisTask]);
+
381 
+
382  qureg.stateVec.imag[thisIndex] = qureg.stateVec.imag[thisIndex] +
+
383  damping*( qureg.pairStateVec.imag[thisTask]);
+
384  } else{
+
385  qureg.stateVec.real[thisIndex] = retain*qureg.stateVec.real[thisIndex];
+
386 
+
387  qureg.stateVec.imag[thisIndex] = retain*qureg.stateVec.imag[thisIndex];
+
388  }
+
389  }
+
390  }
+
391 }
-

References Qureg::chunkId, densmatr_oneQubitDegradeOffDiagonal(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, densmatr_oneQubitDegradeOffDiagonal(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixDamping().

+

Referenced by densmatr_mixDamping().

@@ -1121,60 +1121,60 @@

-

Definition at line 174 of file QuEST_cpu.c.

-
174  {
-
175  qreal retain=1-damping;
-
176  qreal dephase=sqrt(retain);
-
177 
-
178  long long int numTasks = qureg.numAmpsPerChunk;
-
179  long long int innerMask = 1LL << targetQubit;
-
180  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
181  long long int totMask = innerMask|outerMask;
-
182 
-
183  long long int thisTask;
-
184  long long int partner;
-
185  long long int thisPattern;
-
186 
-
187  //qreal realAv, imagAv;
-
188 
-
189 # ifdef _OPENMP
-
190 # pragma omp parallel \
-
191  default (none) \
-
192  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
-
193  private (thisTask,partner,thisPattern)
-
194 # endif
-
195  {
-
196 # ifdef _OPENMP
-
197 # pragma omp for schedule (static)
-
198 # endif
-
199  for (thisTask=0; thisTask<numTasks; thisTask++){
-
200  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
201  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
202  // do dephase
-
203  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
204  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
-
205  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
-
206  } else {
-
207  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
208  // do depolarise
-
209  partner = thisTask | totMask;
-
210  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
211  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
212 
-
213  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
-
214  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
-
215 
-
216  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
-
217  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
-
218  }
-
219  }
-
220  }
-
221  }
-
222 }
+

Definition at line 180 of file QuEST_cpu.c.

+
180  {
+
181  qreal retain=1-damping;
+
182  qreal dephase=sqrt(retain);
+
183 
+
184  long long int numTasks = qureg.numAmpsPerChunk;
+
185  long long int innerMask = 1LL << targetQubit;
+
186  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
187  long long int totMask = innerMask|outerMask;
+
188 
+
189  long long int thisTask;
+
190  long long int partner;
+
191  long long int thisPattern;
+
192 
+
193  //qreal realAv, imagAv;
+
194 
+
195 # ifdef _OPENMP
+
196 # pragma omp parallel \
+
197  default (none) \
+
198  shared (innerMask,outerMask,totMask,qureg,retain,damping,dephase,numTasks) \
+
199  private (thisTask,partner,thisPattern)
+
200 # endif
+
201  {
+
202 # ifdef _OPENMP
+
203 # pragma omp for schedule (static)
+
204 # endif
+
205  for (thisTask=0; thisTask<numTasks; thisTask++){
+
206  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
207  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
208  // do dephase
+
209  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
210  qureg.stateVec.real[thisTask] = dephase*qureg.stateVec.real[thisTask];
+
211  qureg.stateVec.imag[thisTask] = dephase*qureg.stateVec.imag[thisTask];
+
212  } else {
+
213  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
+
214  // do depolarise
+
215  partner = thisTask | totMask;
+
216  //realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
+
217  //imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
+
218 
+
219  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask] + damping*qureg.stateVec.real[partner];
+
220  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask] + damping*qureg.stateVec.imag[partner];
+
221 
+
222  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner];
+
223  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner];
+
224  }
+
225  }
+
226  }
+
227  }
+
228 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixDamping().

+

Referenced by densmatr_mixDamping().

@@ -1210,86 +1210,86 @@

-

Definition at line 224 of file QuEST_cpu.c.

-
224  {
-
225 
-
226  // first do dephase part.
-
227  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
-
228  // iterating over all elements in the state vector for the purpose of vectorisation
-
229  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
-
230  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+

Definition at line 230 of file QuEST_cpu.c.

+
230  {
231 
-
232  long long int sizeInnerBlock, sizeInnerHalfBlock;
-
233  long long int sizeOuterColumn, sizeOuterHalfColumn;
-
234  long long int thisInnerBlock, // current block
-
235  thisOuterColumn, // current column in density matrix
-
236  thisIndex, // current index in (density matrix representation) state vector
-
237  thisIndexInOuterColumn,
-
238  thisIndexInInnerBlock;
-
239  int outerBit;
-
240 
-
241  long long int thisTask;
-
242  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
243 
-
244  // set dimensions
-
245  sizeInnerHalfBlock = 1LL << targetQubit;
-
246  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
-
247  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
248  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
232  // first do dephase part.
+
233  // TODO -- this might be more efficient to do at the same time as the depolarise if we move to
+
234  // iterating over all elements in the state vector for the purpose of vectorisation
+
235  // TODO -- if we keep this split, move this function to densmatr_mixDepolarising()
+
236  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
237 
+
238  long long int sizeInnerBlock, sizeInnerHalfBlock;
+
239  long long int sizeOuterColumn, sizeOuterHalfColumn;
+
240  long long int thisInnerBlock, // current block
+
241  thisOuterColumn, // current column in density matrix
+
242  thisIndex, // current index in (density matrix representation) state vector
+
243  thisIndexInOuterColumn,
+
244  thisIndexInInnerBlock;
+
245  int outerBit;
+
246 
+
247  long long int thisTask;
+
248  long long int numTasks=qureg.numAmpsPerChunk>>1;
249 
-
250 # ifdef _OPENMP
-
251 # pragma omp parallel \
-
252  default (none) \
-
253  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
-
254  qureg,depolLevel,numTasks,targetQubit) \
-
255  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
256  thisIndexInInnerBlock,outerBit)
-
257 # endif
-
258  {
-
259 # ifdef _OPENMP
-
260 # pragma omp for schedule (static)
-
261 # endif
-
262  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
263  // treat this as iterating over all columns, then iterating over half the values
-
264  // within one column.
-
265  // If this function has been called, this process' chunk contains half an
-
266  // outer block or less
-
267  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
268  // we want to process all columns in the density matrix,
-
269  // updating the values for half of each column (one half of each inner block)
-
270  thisOuterColumn = thisTask / sizeOuterHalfColumn;
-
271  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
-
272  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
-
273  // get index in state vector corresponding to upper inner block
-
274  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
-
275  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
-
276  + thisIndexInInnerBlock;
-
277  // check if we are in the upper or lower half of an outer block
-
278  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
279  // if we are in the lower half of an outer block, shift to be in the lower half
-
280  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
281  thisIndex += outerBit*(sizeInnerHalfBlock);
-
282 
-
283  // NOTE: at this point thisIndex should be the index of the element we want to
-
284  // dephase in the chunk of the state vector on this process, in the
-
285  // density matrix representation.
-
286  // thisTask is the index of the pair element in pairStateVec
-
287 
-
288 
-
289  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
290  // + pair[thisTask])/2
-
291  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
-
292  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
-
293 
-
294  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
-
295  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
-
296  }
-
297  }
-
298 }
+
250  // set dimensions
+
251  sizeInnerHalfBlock = 1LL << targetQubit;
+
252  sizeInnerBlock = 2LL * sizeInnerHalfBlock;
+
253  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
254  sizeOuterHalfColumn = sizeOuterColumn >> 1;
+
255 
+
256 # ifdef _OPENMP
+
257 # pragma omp parallel \
+
258  default (none) \
+
259  shared (sizeInnerBlock,sizeInnerHalfBlock,sizeOuterColumn,sizeOuterHalfColumn, \
+
260  qureg,depolLevel,numTasks,targetQubit) \
+
261  private (thisTask,thisInnerBlock,thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
262  thisIndexInInnerBlock,outerBit)
+
263 # endif
+
264  {
+
265 # ifdef _OPENMP
+
266 # pragma omp for schedule (static)
+
267 # endif
+
268  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
269  // treat this as iterating over all columns, then iterating over half the values
+
270  // within one column.
+
271  // If this function has been called, this process' chunk contains half an
+
272  // outer block or less
+
273  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
274  // we want to process all columns in the density matrix,
+
275  // updating the values for half of each column (one half of each inner block)
+
276  thisOuterColumn = thisTask / sizeOuterHalfColumn;
+
277  thisIndexInOuterColumn = thisTask&(sizeOuterHalfColumn-1); // thisTask % sizeOuterHalfColumn
+
278  thisInnerBlock = thisIndexInOuterColumn/sizeInnerHalfBlock;
+
279  // get index in state vector corresponding to upper inner block
+
280  thisIndexInInnerBlock = thisTask&(sizeInnerHalfBlock-1); // thisTask % sizeInnerHalfBlock
+
281  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlock*sizeInnerBlock
+
282  + thisIndexInInnerBlock;
+
283  // check if we are in the upper or lower half of an outer block
+
284  outerBit = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
285  // if we are in the lower half of an outer block, shift to be in the lower half
+
286  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
287  thisIndex += outerBit*(sizeInnerHalfBlock);
+
288 
+
289  // NOTE: at this point thisIndex should be the index of the element we want to
+
290  // dephase in the chunk of the state vector on this process, in the
+
291  // density matrix representation.
+
292  // thisTask is the index of the pair element in pairStateVec
+
293 
+
294 
+
295  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
296  // + pair[thisTask])/2
+
297  qureg.stateVec.real[thisIndex] = (1-depolLevel)*qureg.stateVec.real[thisIndex] +
+
298  depolLevel*(qureg.stateVec.real[thisIndex] + qureg.pairStateVec.real[thisTask])/2;
+
299 
+
300  qureg.stateVec.imag[thisIndex] = (1-depolLevel)*qureg.stateVec.imag[thisIndex] +
+
301  depolLevel*(qureg.stateVec.imag[thisIndex] + qureg.pairStateVec.imag[thisTask])/2;
+
302  }
+
303  }
+
304 }
-

References Qureg::chunkId, densmatr_mixDephasing(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

+

References Qureg::chunkId, densmatr_mixDephasing(), extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixDepolarising().

+

Referenced by densmatr_mixDepolarising().

@@ -1325,59 +1325,59 @@

-

Definition at line 125 of file QuEST_cpu.c.

-
125  {
-
126  qreal retain=1-depolLevel;
-
127 
-
128  long long int numTasks = qureg.numAmpsPerChunk;
-
129  long long int innerMask = 1LL << targetQubit;
-
130  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
-
131  long long int totMask = innerMask|outerMask;
-
132 
-
133  long long int thisTask;
-
134  long long int partner;
-
135  long long int thisPattern;
-
136 
-
137  qreal realAv, imagAv;
-
138 
-
139 # ifdef _OPENMP
-
140 # pragma omp parallel \
-
141  default (none) \
-
142  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
-
143  private (thisTask,partner,thisPattern,realAv,imagAv)
-
144 # endif
-
145  {
-
146 # ifdef _OPENMP
-
147 # pragma omp for schedule (static)
-
148 # endif
-
149  for (thisTask=0; thisTask<numTasks; thisTask++){
-
150  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
-
151  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
-
152  // do dephase
-
153  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
154  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
155  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
156  } else {
-
157  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
-
158  // do depolarise
-
159  partner = thisTask | totMask;
-
160  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
-
161  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
-
162 
-
163  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
-
164  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
-
165 
-
166  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
-
167  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
-
168  }
-
169  }
-
170  }
-
171  }
-
172 }
+

Definition at line 131 of file QuEST_cpu.c.

+
131  {
+
132  qreal retain=1-depolLevel;
+
133 
+
134  long long int numTasks = qureg.numAmpsPerChunk;
+
135  long long int innerMask = 1LL << targetQubit;
+
136  long long int outerMask = 1LL << (targetQubit + (qureg.numQubitsRepresented));
+
137  long long int totMask = innerMask|outerMask;
+
138 
+
139  long long int thisTask;
+
140  long long int partner;
+
141  long long int thisPattern;
+
142 
+
143  qreal realAv, imagAv;
+
144 
+
145 # ifdef _OPENMP
+
146 # pragma omp parallel \
+
147  default (none) \
+
148  shared (innerMask,outerMask,totMask,qureg,retain,depolLevel,numTasks) \
+
149  private (thisTask,partner,thisPattern,realAv,imagAv)
+
150 # endif
+
151  {
+
152 # ifdef _OPENMP
+
153 # pragma omp for schedule (static)
+
154 # endif
+
155  for (thisTask=0; thisTask<numTasks; thisTask++){
+
156  thisPattern = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMask;
+
157  if ((thisPattern==innerMask) || (thisPattern==outerMask)){
+
158  // do dephase
+
159  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
160  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
161  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
162  } else {
+
163  if ((thisTask&totMask)==0){ //this element relates to targetQubit in state 0
+
164  // do depolarise
+
165  partner = thisTask | totMask;
+
166  realAv = (qureg.stateVec.real[thisTask] + qureg.stateVec.real[partner]) /2 ;
+
167  imagAv = (qureg.stateVec.imag[thisTask] + qureg.stateVec.imag[partner]) /2 ;
+
168 
+
169  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask] + depolLevel*realAv;
+
170  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask] + depolLevel*imagAv;
+
171 
+
172  qureg.stateVec.real[partner] = retain*qureg.stateVec.real[partner] + depolLevel*realAv;
+
173  qureg.stateVec.imag[partner] = retain*qureg.stateVec.imag[partner] + depolLevel*imagAv;
+
174  }
+
175  }
+
176  }
+
177  }
+
178 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixDepolarising().

+

Referenced by densmatr_mixDepolarising().

@@ -1425,100 +1425,100 @@

-

Definition at line 541 of file QuEST_cpu.c.

-
542  {
-
543 
-
544  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
545  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
546  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
547  long long int thisInnerBlockQ2,
-
548  thisOuterColumn, // current column in density matrix
-
549  thisIndex, // current index in (density matrix representation) state vector
-
550  thisIndexInOuterColumn,
-
551  thisIndexInInnerBlockQ1,
-
552  thisIndexInInnerBlockQ2,
-
553  thisInnerBlockQ1InInnerBlockQ2;
-
554  int outerBitQ1, outerBitQ2;
-
555 
-
556  long long int thisTask;
-
557  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
558 
-
559  // set dimensions
-
560  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
561  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
562  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
563  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
564  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
565  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
566  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
567 
-
568 # ifdef _OPENMP
-
569 # pragma omp parallel \
-
570  default (none) \
-
571  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
572  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
-
573  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
574  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
-
575  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
576 # endif
-
577  {
-
578 # ifdef _OPENMP
-
579 # pragma omp for schedule (static)
-
580 # endif
-
581  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
582  // treat this as iterating over all columns, then iterating over half the values
-
583  // within one column.
-
584  // If this function has been called, this process' chunk contains half an
-
585  // outer block or less
-
586  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
587  // we want to process all columns in the density matrix,
-
588  // updating the values for half of each column (one half of each inner block)
-
589  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
590  // thisTask % sizeOuterQuarterColumn
-
591  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
592  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
593  // thisTask % sizeInnerQuarterBlockQ2;
-
594  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
595  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
596  // thisTask % sizeInnerHalfBlockQ1;
-
597  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
598 
-
599  // get index in state vector corresponding to upper inner block
-
600  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
601  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
602 
-
603  // check if we are in the upper or lower half of an outer block for Q1
-
604  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
605  // if we are in the lower half of an outer block, shift to be in the lower half
-
606  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
607  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+

Definition at line 547 of file QuEST_cpu.c.

+
548  {
+
549 
+
550  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
551  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
552  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
553  long long int thisInnerBlockQ2,
+
554  thisOuterColumn, // current column in density matrix
+
555  thisIndex, // current index in (density matrix representation) state vector
+
556  thisIndexInOuterColumn,
+
557  thisIndexInInnerBlockQ1,
+
558  thisIndexInInnerBlockQ2,
+
559  thisInnerBlockQ1InInnerBlockQ2;
+
560  int outerBitQ1, outerBitQ2;
+
561 
+
562  long long int thisTask;
+
563  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
564 
+
565  // set dimensions
+
566  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
567  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
568  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
569  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
570  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
571  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
572  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
573 
+
574 # ifdef _OPENMP
+
575 # pragma omp parallel \
+
576  default (none) \
+
577  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
+
578  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma,numTasks,targetQubit,qubit2) \
+
579  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
+
580  thisOuterColumn,thisIndex,thisIndexInOuterColumn, \
+
581  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
+
582 # endif
+
583  {
+
584 # ifdef _OPENMP
+
585 # pragma omp for schedule (static)
+
586 # endif
+
587  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
588  // treat this as iterating over all columns, then iterating over half the values
+
589  // within one column.
+
590  // If this function has been called, this process' chunk contains half an
+
591  // outer block or less
+
592  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
593  // we want to process all columns in the density matrix,
+
594  // updating the values for half of each column (one half of each inner block)
+
595  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
596  // thisTask % sizeOuterQuarterColumn
+
597  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
598  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
599  // thisTask % sizeInnerQuarterBlockQ2;
+
600  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
601  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
602  // thisTask % sizeInnerHalfBlockQ1;
+
603  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
+
604 
+
605  // get index in state vector corresponding to upper inner block
+
606  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
607  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
608 
-
609  // check if we are in the upper or lower half of an outer block for Q2
-
610  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
609  // check if we are in the upper or lower half of an outer block for Q1
+
610  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
611  // if we are in the lower half of an outer block, shift to be in the lower half
612  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
613  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
613  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
614 
-
615  // NOTE: at this point thisIndex should be the index of the element we want to
-
616  // dephase in the chunk of the state vector on this process, in the
-
617  // density matrix representation.
-
618  // thisTask is the index of the pair element in pairStateVec
-
619 
-
620 
-
621  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
622  // + pair[thisTask])/2
-
623  // NOTE: must set gamma=1 if using this function for steps 1 or 2
-
624  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
625  delta*qureg.pairStateVec.real[thisTask]);
-
626  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
627  delta*qureg.pairStateVec.imag[thisTask]);
-
628  }
-
629  }
-
630 }
+
615  // check if we are in the upper or lower half of an outer block for Q2
+
616  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
617  // if we are in the lower half of an outer block, shift to be in the lower half
+
618  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
619  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
620 
+
621  // NOTE: at this point thisIndex should be the index of the element we want to
+
622  // dephase in the chunk of the state vector on this process, in the
+
623  // density matrix representation.
+
624  // thisTask is the index of the pair element in pairStateVec
+
625 
+
626 
+
627  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
628  // + pair[thisTask])/2
+
629  // NOTE: must set gamma=1 if using this function for steps 1 or 2
+
630  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
+
631  delta*qureg.pairStateVec.real[thisTask]);
+
632  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
+
633  delta*qureg.pairStateVec.imag[thisTask]);
+
634  }
+
635  }
+
636 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -1566,111 +1566,111 @@

-

Definition at line 387 of file QuEST_cpu.c.

-
387  {
-
388  long long int numTasks = qureg.numAmpsPerChunk;
-
389  long long int innerMaskQubit1 = 1LL << qubit1;
-
390  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
391  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
392  long long int innerMaskQubit2 = 1LL << qubit2;
-
393  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
394  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
395 
-
396  long long int thisTask;
-
397  long long int partner;
-
398  long long int thisPatternQubit1, thisPatternQubit2;
-
399 
-
400  qreal real00, imag00;
+

Definition at line 393 of file QuEST_cpu.c.

+
393  {
+
394  long long int numTasks = qureg.numAmpsPerChunk;
+
395  long long int innerMaskQubit1 = 1LL << qubit1;
+
396  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
+
397  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
+
398  long long int innerMaskQubit2 = 1LL << qubit2;
+
399  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
+
400  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
401 
-
402 # ifdef _OPENMP
-
403 # pragma omp parallel \
-
404  default (none) \
-
405  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
-
406  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
407 # endif
-
408  {
-
409 # ifdef _OPENMP
-
410 # pragma omp for schedule (static)
-
411 # endif
-
412  //--------------------------------------- STEP ONE ---------------------
-
413  for (thisTask=0; thisTask<numTasks; thisTask++){
-
414  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
415  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
416  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
417  || (thisPatternQubit2==totMaskQubit2))){
-
418  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
419  partner = thisTask | totMaskQubit1;
-
420  real00 = qureg.stateVec.real[thisTask];
-
421  imag00 = qureg.stateVec.imag[thisTask];
-
422 
-
423  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
424  + delta*qureg.stateVec.real[partner];
-
425  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
426  + delta*qureg.stateVec.imag[partner];
-
427 
-
428  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
429  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
430 
-
431  }
-
432  }
-
433 # ifdef _OPENMP
-
434 # pragma omp for schedule (static)
-
435 # endif
-
436  //--------------------------------------- STEP TWO ---------------------
-
437  for (thisTask=0; thisTask<numTasks; thisTask++){
-
438  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
439  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
440  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
441  || (thisPatternQubit1==totMaskQubit1))){
-
442  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
443  partner = thisTask | totMaskQubit2;
-
444  real00 = qureg.stateVec.real[thisTask];
-
445  imag00 = qureg.stateVec.imag[thisTask];
-
446 
-
447  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
448  + delta*qureg.stateVec.real[partner];
-
449  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
450  + delta*qureg.stateVec.imag[partner];
-
451 
-
452  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
453  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
454 
-
455  }
-
456  }
-
457 
-
458 # ifdef _OPENMP
-
459 # pragma omp for schedule (static)
-
460 # endif
-
461  //--------------------------------------- STEP THREE ---------------------
-
462  for (thisTask=0; thisTask<numTasks; thisTask++){
-
463  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
464  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
465  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
-
466  || (thisPatternQubit1==totMaskQubit1))){
-
467  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
-
468  partner = thisTask | totMaskQubit2;
-
469  partner = partner ^ totMaskQubit1;
-
470  real00 = qureg.stateVec.real[thisTask];
-
471  imag00 = qureg.stateVec.imag[thisTask];
-
472 
-
473  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
-
474  + delta*qureg.stateVec.real[partner]);
-
475  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
-
476  + delta*qureg.stateVec.imag[partner]);
-
477 
-
478  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
-
479  + delta*real00);
-
480  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
-
481  + delta*imag00);
-
482 
-
483  }
-
484  }
-
485  }
-
486 }
+
402  long long int thisTask;
+
403  long long int partner;
+
404  long long int thisPatternQubit1, thisPatternQubit2;
+
405 
+
406  qreal real00, imag00;
+
407 
+
408 # ifdef _OPENMP
+
409 # pragma omp parallel \
+
410  default (none) \
+
411  shared (totMaskQubit1,totMaskQubit2,qureg,delta,gamma,numTasks) \
+
412  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
+
413 # endif
+
414  {
+
415 # ifdef _OPENMP
+
416 # pragma omp for schedule (static)
+
417 # endif
+
418  //--------------------------------------- STEP ONE ---------------------
+
419  for (thisTask=0; thisTask<numTasks; thisTask++){
+
420  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
421  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
422  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
+
423  || (thisPatternQubit2==totMaskQubit2))){
+
424  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
+
425  partner = thisTask | totMaskQubit1;
+
426  real00 = qureg.stateVec.real[thisTask];
+
427  imag00 = qureg.stateVec.imag[thisTask];
+
428 
+
429  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
430  + delta*qureg.stateVec.real[partner];
+
431  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
432  + delta*qureg.stateVec.imag[partner];
+
433 
+
434  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
435  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
436 
+
437  }
+
438  }
+
439 # ifdef _OPENMP
+
440 # pragma omp for schedule (static)
+
441 # endif
+
442  //--------------------------------------- STEP TWO ---------------------
+
443  for (thisTask=0; thisTask<numTasks; thisTask++){
+
444  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
445  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
446  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
+
447  || (thisPatternQubit1==totMaskQubit1))){
+
448  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
+
449  partner = thisTask | totMaskQubit2;
+
450  real00 = qureg.stateVec.real[thisTask];
+
451  imag00 = qureg.stateVec.imag[thisTask];
+
452 
+
453  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
454  + delta*qureg.stateVec.real[partner];
+
455  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
456  + delta*qureg.stateVec.imag[partner];
+
457 
+
458  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
459  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
460 
+
461  }
+
462  }
+
463 
+
464 # ifdef _OPENMP
+
465 # pragma omp for schedule (static)
+
466 # endif
+
467  //--------------------------------------- STEP THREE ---------------------
+
468  for (thisTask=0; thisTask<numTasks; thisTask++){
+
469  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
470  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
471  if ((thisPatternQubit2==0) && ((thisPatternQubit1==0)
+
472  || (thisPatternQubit1==totMaskQubit1))){
+
473  //this element of form |...0...X...><...0...X...| for X either 0 or 1.
+
474  partner = thisTask | totMaskQubit2;
+
475  partner = partner ^ totMaskQubit1;
+
476  real00 = qureg.stateVec.real[thisTask];
+
477  imag00 = qureg.stateVec.imag[thisTask];
+
478 
+
479  qureg.stateVec.real[thisTask] = gamma * (qureg.stateVec.real[thisTask]
+
480  + delta*qureg.stateVec.real[partner]);
+
481  qureg.stateVec.imag[thisTask] = gamma * (qureg.stateVec.imag[thisTask]
+
482  + delta*qureg.stateVec.imag[partner]);
+
483 
+
484  qureg.stateVec.real[partner] = gamma * (qureg.stateVec.real[partner]
+
485  + delta*real00);
+
486  qureg.stateVec.imag[partner] = gamma * (qureg.stateVec.imag[partner]
+
487  + delta*imag00);
+
488 
+
489  }
+
490  }
+
491  }
+
492 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -1712,63 +1712,63 @@

-

Definition at line 488 of file QuEST_cpu.c.

-
488  {
-
489  long long int numTasks = qureg.numAmpsPerChunk;
-
490  long long int innerMaskQubit1 = 1LL << qubit1;
-
491  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
-
492  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
-
493  long long int innerMaskQubit2 = 1LL << qubit2;
-
494  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
-
495  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
-
496  // correct for being in a particular chunk
-
497  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
-
498 
-
499 
-
500  long long int thisTask;
-
501  long long int partner;
-
502  long long int thisPatternQubit1, thisPatternQubit2;
-
503 
-
504  qreal real00, imag00;
+

Definition at line 494 of file QuEST_cpu.c.

+
494  {
+
495  long long int numTasks = qureg.numAmpsPerChunk;
+
496  long long int innerMaskQubit1 = 1LL << qubit1;
+
497  long long int outerMaskQubit1= 1LL << (qubit1 + qureg.numQubitsRepresented);
+
498  long long int totMaskQubit1 = innerMaskQubit1 | outerMaskQubit1;
+
499  long long int innerMaskQubit2 = 1LL << qubit2;
+
500  long long int outerMaskQubit2 = 1LL << (qubit2 + qureg.numQubitsRepresented);
+
501  long long int totMaskQubit2 = innerMaskQubit2 | outerMaskQubit2;
+
502  // correct for being in a particular chunk
+
503  //totMaskQubit2 = totMaskQubit2&(qureg.numAmpsPerChunk-1); // totMaskQubit2 % numAmpsPerChunk
+
504 
505 
-
506 # ifdef _OPENMP
-
507 # pragma omp parallel \
-
508  default (none) \
-
509  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
-
510  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
-
511 # endif
-
512  {
-
513 
-
514 # ifdef _OPENMP
-
515 # pragma omp for schedule (static)
-
516 # endif
-
517  //--------------------------------------- STEP ONE ---------------------
-
518  for (thisTask=0; thisTask<numTasks; thisTask ++){
-
519  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
520  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
521  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
-
522  || (thisPatternQubit2==totMaskQubit2))){
-
523  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
-
524  partner = thisTask | totMaskQubit1;
-
525  real00 = qureg.stateVec.real[thisTask];
-
526  imag00 = qureg.stateVec.imag[thisTask];
-
527 
-
528  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
-
529  + delta*qureg.stateVec.real[partner];
-
530  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
-
531  + delta*qureg.stateVec.imag[partner];
-
532 
-
533  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
-
534  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
-
535 
-
536  }
-
537  }
-
538  }
-
539 }
+
506  long long int thisTask;
+
507  long long int partner;
+
508  long long int thisPatternQubit1, thisPatternQubit2;
+
509 
+
510  qreal real00, imag00;
+
511 
+
512 # ifdef _OPENMP
+
513 # pragma omp parallel \
+
514  default (none) \
+
515  shared (totMaskQubit1,totMaskQubit2,qureg,delta,numTasks) \
+
516  private (thisTask,partner,thisPatternQubit1,thisPatternQubit2,real00,imag00)
+
517 # endif
+
518  {
+
519 
+
520 # ifdef _OPENMP
+
521 # pragma omp for schedule (static)
+
522 # endif
+
523  //--------------------------------------- STEP ONE ---------------------
+
524  for (thisTask=0; thisTask<numTasks; thisTask ++){
+
525  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
526  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
527  if ((thisPatternQubit1==0) && ((thisPatternQubit2==0)
+
528  || (thisPatternQubit2==totMaskQubit2))){
+
529  //this element of form |...X...0...><...X...0...| for X either 0 or 1.
+
530  partner = thisTask | totMaskQubit1;
+
531  real00 = qureg.stateVec.real[thisTask];
+
532  imag00 = qureg.stateVec.imag[thisTask];
+
533 
+
534  qureg.stateVec.real[thisTask] = qureg.stateVec.real[thisTask]
+
535  + delta*qureg.stateVec.real[partner];
+
536  qureg.stateVec.imag[thisTask] = qureg.stateVec.imag[thisTask]
+
537  + delta*qureg.stateVec.imag[partner];
+
538 
+
539  qureg.stateVec.real[partner] = qureg.stateVec.real[partner] + delta*real00;
+
540  qureg.stateVec.imag[partner] = qureg.stateVec.imag[partner] + delta*imag00;
+
541 
+
542  }
+
543  }
+
544  }
+
545 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -1816,109 +1816,109 @@

-

Definition at line 632 of file QuEST_cpu.c.

-
633  {
-
634 
-
635  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
-
636  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
-
637  long long int sizeOuterColumn, sizeOuterQuarterColumn;
-
638  long long int thisInnerBlockQ2,
-
639  thisOuterColumn, // current column in density matrix
-
640  thisIndex, // current index in (density matrix representation) state vector
-
641  thisIndexInPairVector,
-
642  thisIndexInOuterColumn,
-
643  thisIndexInInnerBlockQ1,
-
644  thisIndexInInnerBlockQ2,
-
645  thisInnerBlockQ1InInnerBlockQ2;
-
646  int outerBitQ1, outerBitQ2;
-
647 
-
648  long long int thisTask;
-
649  long long int numTasks=qureg.numAmpsPerChunk>>2;
-
650 
-
651  // set dimensions
-
652  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
-
653  sizeInnerHalfBlockQ2 = 1LL << qubit2;
-
654  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
-
655  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
-
656  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
-
657  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
-
658  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
-
659 
-
660 //# if 0
-
661 # ifdef _OPENMP
-
662 # pragma omp parallel \
-
663  default (none) \
-
664  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
-
665  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
-
666  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
-
667  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
-
668  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
-
669 # endif
-
670  {
-
671 # ifdef _OPENMP
-
672 # pragma omp for schedule (static)
-
673 # endif
-
674 //# endif
-
675  // thisTask iterates over half the elements in this process' chunk of the density matrix
-
676  // treat this as iterating over all columns, then iterating over half the values
-
677  // within one column.
-
678  // If this function has been called, this process' chunk contains half an
-
679  // outer block or less
-
680  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
681  // we want to process all columns in the density matrix,
-
682  // updating the values for half of each column (one half of each inner block)
-
683  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
-
684  // thisTask % sizeOuterQuarterColumn
-
685  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
-
686  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
-
687  // thisTask % sizeInnerQuarterBlockQ2;
-
688  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
-
689  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
-
690  // thisTask % sizeInnerHalfBlockQ1;
-
691  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
-
692 
-
693  // get index in state vector corresponding to upper inner block
-
694  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
-
695  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
-
696 
-
697  // check if we are in the upper or lower half of an outer block for Q1
-
698  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
699  // if we are in the lower half of an outer block, shift to be in the lower half
-
700  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
701  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
-
702 
-
703  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
-
704  // Find correct index in pairStateVector
-
705  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
-
706  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
-
707 
-
708  // check if we are in the upper or lower half of an outer block for Q2
-
709  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
-
710  // if we are in the lower half of an outer block, shift to be in the lower half
-
711  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
-
712  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+

Definition at line 638 of file QuEST_cpu.c.

+
639  {
+
640 
+
641  long long int sizeInnerBlockQ1, sizeInnerHalfBlockQ1;
+
642  long long int sizeInnerBlockQ2, sizeInnerHalfBlockQ2, sizeInnerQuarterBlockQ2;
+
643  long long int sizeOuterColumn, sizeOuterQuarterColumn;
+
644  long long int thisInnerBlockQ2,
+
645  thisOuterColumn, // current column in density matrix
+
646  thisIndex, // current index in (density matrix representation) state vector
+
647  thisIndexInPairVector,
+
648  thisIndexInOuterColumn,
+
649  thisIndexInInnerBlockQ1,
+
650  thisIndexInInnerBlockQ2,
+
651  thisInnerBlockQ1InInnerBlockQ2;
+
652  int outerBitQ1, outerBitQ2;
+
653 
+
654  long long int thisTask;
+
655  long long int numTasks=qureg.numAmpsPerChunk>>2;
+
656 
+
657  // set dimensions
+
658  sizeInnerHalfBlockQ1 = 1LL << targetQubit;
+
659  sizeInnerHalfBlockQ2 = 1LL << qubit2;
+
660  sizeInnerQuarterBlockQ2 = sizeInnerHalfBlockQ2 >> 1;
+
661  sizeInnerBlockQ2 = sizeInnerHalfBlockQ2 << 1;
+
662  sizeInnerBlockQ1 = 2LL * sizeInnerHalfBlockQ1;
+
663  sizeOuterColumn = 1LL << qureg.numQubitsRepresented;
+
664  sizeOuterQuarterColumn = sizeOuterColumn >> 2;
+
665 
+
666 //# if 0
+
667 # ifdef _OPENMP
+
668 # pragma omp parallel \
+
669  default (none) \
+
670  shared (sizeInnerBlockQ1,sizeInnerHalfBlockQ1,sizeInnerBlockQ2,sizeInnerHalfBlockQ2,sizeInnerQuarterBlockQ2,\
+
671  sizeOuterColumn,sizeOuterQuarterColumn,qureg,delta,gamma, numTasks,targetQubit,qubit2) \
+
672  private (thisTask,thisInnerBlockQ2,thisInnerBlockQ1InInnerBlockQ2, \
+
673  thisOuterColumn,thisIndex,thisIndexInPairVector,thisIndexInOuterColumn, \
+
674  thisIndexInInnerBlockQ1,thisIndexInInnerBlockQ2,outerBitQ1,outerBitQ2)
+
675 # endif
+
676  {
+
677 # ifdef _OPENMP
+
678 # pragma omp for schedule (static)
+
679 # endif
+
680 //# endif
+
681  // thisTask iterates over half the elements in this process' chunk of the density matrix
+
682  // treat this as iterating over all columns, then iterating over half the values
+
683  // within one column.
+
684  // If this function has been called, this process' chunk contains half an
+
685  // outer block or less
+
686  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
687  // we want to process all columns in the density matrix,
+
688  // updating the values for half of each column (one half of each inner block)
+
689  thisOuterColumn = thisTask / sizeOuterQuarterColumn;
+
690  // thisTask % sizeOuterQuarterColumn
+
691  thisIndexInOuterColumn = thisTask&(sizeOuterQuarterColumn-1);
+
692  thisInnerBlockQ2 = thisIndexInOuterColumn / sizeInnerQuarterBlockQ2;
+
693  // thisTask % sizeInnerQuarterBlockQ2;
+
694  thisIndexInInnerBlockQ2 = thisTask&(sizeInnerQuarterBlockQ2-1);
+
695  thisInnerBlockQ1InInnerBlockQ2 = thisIndexInInnerBlockQ2 / sizeInnerHalfBlockQ1;
+
696  // thisTask % sizeInnerHalfBlockQ1;
+
697  thisIndexInInnerBlockQ1 = thisTask&(sizeInnerHalfBlockQ1-1);
+
698 
+
699  // get index in state vector corresponding to upper inner block
+
700  thisIndex = thisOuterColumn*sizeOuterColumn + thisInnerBlockQ2*sizeInnerBlockQ2
+
701  + thisInnerBlockQ1InInnerBlockQ2*sizeInnerBlockQ1 + thisIndexInInnerBlockQ1;
+
702 
+
703  // check if we are in the upper or lower half of an outer block for Q1
+
704  outerBitQ1 = extractBit(targetQubit, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
705  // if we are in the lower half of an outer block, shift to be in the lower half
+
706  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
707  thisIndex += outerBitQ1*(sizeInnerHalfBlockQ1);
+
708 
+
709  // For part 3 we need to match elements such that (my Q1 != pair Q1) AND (my Q2 != pair Q2)
+
710  // Find correct index in pairStateVector
+
711  thisIndexInPairVector = thisTask + (1-outerBitQ1)*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn -
+
712  outerBitQ1*sizeInnerHalfBlockQ1*sizeOuterQuarterColumn;
713 
-
714 
-
715  // NOTE: at this point thisIndex should be the index of the element we want to
-
716  // dephase in the chunk of the state vector on this process, in the
-
717  // density matrix representation.
-
718 
-
719 
-
720  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
-
721  // + pair[thisIndexInPairVector])/2
-
722  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
-
723  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
-
724 
-
725  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
-
726  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
-
727  }
-
728  }
-
729 
-
730 }
+
714  // check if we are in the upper or lower half of an outer block for Q2
+
715  outerBitQ2 = extractBit(qubit2, (thisIndex+qureg.numAmpsPerChunk*qureg.chunkId)>>qureg.numQubitsRepresented);
+
716  // if we are in the lower half of an outer block, shift to be in the lower half
+
717  // of the inner block as well (we want to dephase |0><0| and |1><1| only)
+
718  thisIndex += outerBitQ2*(sizeInnerQuarterBlockQ2<<1);
+
719 
+
720 
+
721  // NOTE: at this point thisIndex should be the index of the element we want to
+
722  // dephase in the chunk of the state vector on this process, in the
+
723  // density matrix representation.
+
724 
+
725 
+
726  // state[thisIndex] = (1-depolLevel)*state[thisIndex] + depolLevel*(state[thisIndex]
+
727  // + pair[thisIndexInPairVector])/2
+
728  qureg.stateVec.real[thisIndex] = gamma*(qureg.stateVec.real[thisIndex] +
+
729  delta*qureg.pairStateVec.real[thisIndexInPairVector]);
+
730 
+
731  qureg.stateVec.imag[thisIndex] = gamma*(qureg.stateVec.imag[thisIndex] +
+
732  delta*qureg.pairStateVec.imag[thisIndexInPairVector]);
+
733  }
+
734  }
+
735 
+
736 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, Qureg::pairStateVec, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising().

+

Referenced by densmatr_mixTwoQubitDepolarising().

@@ -2150,7 +2150,7 @@

References extractBit().

-

Referenced by statevec_swapQubitAmpsDistributed().

+

Referenced by statevec_swapQubitAmpsDistributed().

@@ -2193,7 +2193,7 @@

35  return mask & (1LL << bitInd);
36 }
-

Referenced by statevec_multiControlledMultiQubitUnitary(), and statevec_multiControlledTwoQubitUnitary().

+

Referenced by statevec_multiControlledMultiQubitUnitary(), and statevec_multiControlledTwoQubitUnitary().

@@ -2223,53 +2223,53 @@

-

Definition at line 4084 of file QuEST_cpu.c.

-
4084  {
-
4085 
-
4086  qreal expecRe = 0;
-
4087  qreal expecIm = 0;
-
4088 
-
4089  long long int index;
-
4090  long long int numAmps = qureg.numAmpsPerChunk;
-
4091  qreal *stateReal = qureg.stateVec.real;
-
4092  qreal *stateImag = qureg.stateVec.imag;
-
4093  qreal *opReal = op.real;
-
4094  qreal *opImag = op.imag;
-
4095 
-
4096  qreal vecRe,vecIm,vecAbs, opRe, opIm;
-
4097 
-
4098 # ifdef _OPENMP
-
4099 # pragma omp parallel \
-
4100  shared (stateReal, stateImag, opReal, opImag, numAmps) \
-
4101  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
-
4102  reduction ( +:expecRe, expecIm )
-
4103 # endif
-
4104  {
-
4105 # ifdef _OPENMP
-
4106 # pragma omp for schedule (static)
-
4107 # endif
-
4108  for (index=0; index < numAmps; index++) {
-
4109  vecRe = stateReal[index];
-
4110  vecIm = stateImag[index];
-
4111  opRe = opReal[index];
-
4112  opIm = opImag[index];
-
4113 
-
4114  // abs(vec)^2 op
-
4115  vecAbs = vecRe*vecRe + vecIm*vecIm;
-
4116  expecRe += vecAbs*opRe;
-
4117  expecIm += vecAbs*opIm;
-
4118  }
-
4119  }
-
4120 
-
4121  Complex innerProd;
-
4122  innerProd.real = expecRe;
-
4123  innerProd.imag = expecIm;
-
4124  return innerProd;
-
4125 }
+

Definition at line 4124 of file QuEST_cpu.c.

+
4124  {
+
4125 
+
4126  qreal expecRe = 0;
+
4127  qreal expecIm = 0;
+
4128 
+
4129  long long int index;
+
4130  long long int numAmps = qureg.numAmpsPerChunk;
+
4131  qreal *stateReal = qureg.stateVec.real;
+
4132  qreal *stateImag = qureg.stateVec.imag;
+
4133  qreal *opReal = op.real;
+
4134  qreal *opImag = op.imag;
+
4135 
+
4136  qreal vecRe,vecIm,vecAbs, opRe, opIm;
+
4137 
+
4138 # ifdef _OPENMP
+
4139 # pragma omp parallel \
+
4140  shared (stateReal, stateImag, opReal, opImag, numAmps) \
+
4141  private (index, vecRe,vecIm,vecAbs, opRe,opIm) \
+
4142  reduction ( +:expecRe, expecIm )
+
4143 # endif
+
4144  {
+
4145 # ifdef _OPENMP
+
4146 # pragma omp for schedule (static)
+
4147 # endif
+
4148  for (index=0; index < numAmps; index++) {
+
4149  vecRe = stateReal[index];
+
4150  vecIm = stateImag[index];
+
4151  opRe = opReal[index];
+
4152  opIm = opImag[index];
+
4153 
+
4154  // abs(vec)^2 op
+
4155  vecAbs = vecRe*vecRe + vecIm*vecIm;
+
4156  expecRe += vecAbs*opRe;
+
4157  expecIm += vecAbs*opIm;
+
4158  }
+
4159  }
+
4160 
+
4161  Complex innerProd;
+
4162  innerProd.real = expecRe;
+
4163  innerProd.imag = expecIm;
+
4164  return innerProd;
+
4165 }

References Complex::imag, DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, DiagonalOp::real, and Qureg::stateVec.

-

Referenced by statevec_calcExpecDiagonalOp().

+

Referenced by statevec_calcExpecDiagonalOp().

@@ -2299,48 +2299,48 @@

-

Definition at line 1071 of file QuEST_cpu.c.

-
1071  {
-
1072 
-
1073  qreal innerProdReal = 0;
-
1074  qreal innerProdImag = 0;
-
1075 
-
1076  long long int index;
-
1077  long long int numAmps = bra.numAmpsPerChunk;
-
1078  qreal *braVecReal = bra.stateVec.real;
-
1079  qreal *braVecImag = bra.stateVec.imag;
-
1080  qreal *ketVecReal = ket.stateVec.real;
-
1081  qreal *ketVecImag = ket.stateVec.imag;
-
1082 
-
1083  qreal braRe, braIm, ketRe, ketIm;
-
1084 
-
1085 # ifdef _OPENMP
-
1086 # pragma omp parallel \
-
1087  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
-
1088  private (index, braRe, braIm, ketRe, ketIm) \
-
1089  reduction ( +:innerProdReal, innerProdImag )
-
1090 # endif
-
1091  {
-
1092 # ifdef _OPENMP
-
1093 # pragma omp for schedule (static)
-
1094 # endif
-
1095  for (index=0; index < numAmps; index++) {
-
1096  braRe = braVecReal[index];
-
1097  braIm = braVecImag[index];
-
1098  ketRe = ketVecReal[index];
-
1099  ketIm = ketVecImag[index];
-
1100 
-
1101  // conj(bra_i) * ket_i
-
1102  innerProdReal += braRe*ketRe + braIm*ketIm;
-
1103  innerProdImag += braRe*ketIm - braIm*ketRe;
-
1104  }
-
1105  }
-
1106 
-
1107  Complex innerProd;
-
1108  innerProd.real = innerProdReal;
-
1109  innerProd.imag = innerProdImag;
-
1110  return innerProd;
-
1111 }
+

Definition at line 1082 of file QuEST_cpu.c.

+
1082  {
+
1083 
+
1084  qreal innerProdReal = 0;
+
1085  qreal innerProdImag = 0;
+
1086 
+
1087  long long int index;
+
1088  long long int numAmps = bra.numAmpsPerChunk;
+
1089  qreal *braVecReal = bra.stateVec.real;
+
1090  qreal *braVecImag = bra.stateVec.imag;
+
1091  qreal *ketVecReal = ket.stateVec.real;
+
1092  qreal *ketVecImag = ket.stateVec.imag;
+
1093 
+
1094  qreal braRe, braIm, ketRe, ketIm;
+
1095 
+
1096 # ifdef _OPENMP
+
1097 # pragma omp parallel \
+
1098  shared (braVecReal, braVecImag, ketVecReal, ketVecImag, numAmps) \
+
1099  private (index, braRe, braIm, ketRe, ketIm) \
+
1100  reduction ( +:innerProdReal, innerProdImag )
+
1101 # endif
+
1102  {
+
1103 # ifdef _OPENMP
+
1104 # pragma omp for schedule (static)
+
1105 # endif
+
1106  for (index=0; index < numAmps; index++) {
+
1107  braRe = braVecReal[index];
+
1108  braIm = braVecImag[index];
+
1109  ketRe = ketVecReal[index];
+
1110  ketIm = ketVecImag[index];
+
1111 
+
1112  // conj(bra_i) * ket_i
+
1113  innerProdReal += braRe*ketRe + braIm*ketIm;
+
1114  innerProdImag += braRe*ketIm - braIm*ketRe;
+
1115  }
+
1116  }
+
1117 
+
1118  Complex innerProd;
+
1119  innerProd.real = innerProdReal;
+
1120  innerProd.imag = innerProdImag;
+
1121  return innerProd;
+
1122 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

@@ -2386,76 +2386,77 @@

-

Definition at line 3510 of file QuEST_cpu.c.

-
3510  {
-
3511 
-
3512  /* Below, we manually reduce amplitudes into outcomeProbs by using atomic update.
-
3513  * This maintains OpenMP 3.1 compatibility. An alternative is to use array reduction
-
3514  * (requires OpenMP 4.5, limits #qubits since outcomeProbs must be a local stack array)
-
3515  * or a dynamic list of omp locks (duplicates memory cost of outcomeProbs).
-
3516  * Using locks was always slower than the method below. Using reduction was only
-
3517  * faster for very few threads, or very few outcomeProbs.
-
3518  */
-
3519 
-
3520  long long int numOutcomeProbs = (1 << numQubits);
-
3521  long long int j;
-
3522 
-
3523  // clear outcomeProbs (in parallel, in case it's large)
-
3524 # ifdef _OPENMP
-
3525 # pragma omp parallel \
-
3526  default (none) \
-
3527  shared (numOutcomeProbs,outcomeProbs) \
-
3528  private (j)
-
3529 # endif
-
3530  {
-
3531 # ifdef _OPENMP
-
3532 # pragma omp for schedule (static)
-
3533 # endif
-
3534  for (j=0; j<numOutcomeProbs; j++)
-
3535  outcomeProbs[j] = 0;
-
3536  }
-
3537 
-
3538  long long int numTasks = qureg.numAmpsPerChunk;
-
3539  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk;
-
3540  qreal* stateRe = qureg.stateVec.real;
-
3541  qreal* stateIm = qureg.stateVec.imag;
-
3542 
-
3543  long long int i;
-
3544  long long int outcomeInd;
-
3545  int q;
-
3546  qreal prob;
-
3547 
-
3548 # ifdef _OPENMP
-
3549 # pragma omp parallel \
-
3550  shared (numTasks,offset, qubits,numQubits, stateRe,stateIm, outcomeProbs) \
-
3551  private (i, q, outcomeInd, prob)
-
3552 # endif
-
3553  {
-
3554 # ifdef _OPENMP
-
3555 # pragma omp for schedule (static)
-
3556 # endif
-
3557  // every amplitude contributes to a single element of retProbs
-
3558  for (i=0; i<numTasks; i++) {
-
3559 
-
3560  // determine index informed by qubits outcome
-
3561  outcomeInd = 0;
-
3562  for (q=0; q<numQubits; q++)
-
3563  outcomeInd += extractBit(qubits[q], i + offset) * (1LL << q);
-
3564 
-
3565  prob = stateRe[i]*stateRe[i] + stateIm[i]*stateIm[i];
-
3566 
-
3567  // atomicly update corresponding outcome array element
-
3568  # ifdef _OPENMP
-
3569  # pragma omp atomic update
-
3570  # endif
-
3571  outcomeProbs[outcomeInd] += prob;
-
3572  }
-
3573  }
-
3574 }
+

Definition at line 3549 of file QuEST_cpu.c.

+
3549  {
+
3550 
+
3551  /* Below, we manually reduce amplitudes into outcomeProbs by using atomic update.
+
3552  * This maintains OpenMP 3.1 compatibility. An alternative is to use array reduction
+
3553  * (requires OpenMP 4.5, limits #qubits since outcomeProbs must be a local stack array)
+
3554  * or a dynamic list of omp locks (duplicates memory cost of outcomeProbs).
+
3555  * Using locks was always slower than the method below. Using reduction was only
+
3556  * faster for very few threads, or very few outcomeProbs.
+
3557  * Finally, we exclude the 'update' clause after 'atomic' to maintain MSVC compatibility
+
3558  */
+
3559 
+
3560  long long int numOutcomeProbs = (1 << numQubits);
+
3561  long long int j;
+
3562 
+
3563  // clear outcomeProbs (in parallel, in case it's large)
+
3564 # ifdef _OPENMP
+
3565 # pragma omp parallel \
+
3566  default (none) \
+
3567  shared (numOutcomeProbs,outcomeProbs) \
+
3568  private (j)
+
3569 # endif
+
3570  {
+
3571 # ifdef _OPENMP
+
3572 # pragma omp for schedule (static)
+
3573 # endif
+
3574  for (j=0; j<numOutcomeProbs; j++)
+
3575  outcomeProbs[j] = 0;
+
3576  }
+
3577 
+
3578  long long int numTasks = qureg.numAmpsPerChunk;
+
3579  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk;
+
3580  qreal* stateRe = qureg.stateVec.real;
+
3581  qreal* stateIm = qureg.stateVec.imag;
+
3582 
+
3583  long long int i;
+
3584  long long int outcomeInd;
+
3585  int q;
+
3586  qreal prob;
+
3587 
+
3588 # ifdef _OPENMP
+
3589 # pragma omp parallel \
+
3590  shared (numTasks,offset, qubits,numQubits, stateRe,stateIm, outcomeProbs) \
+
3591  private (i, q, outcomeInd, prob)
+
3592 # endif
+
3593  {
+
3594 # ifdef _OPENMP
+
3595 # pragma omp for schedule (static)
+
3596 # endif
+
3597  // every amplitude contributes to a single element of retProbs
+
3598  for (i=0; i<numTasks; i++) {
+
3599 
+
3600  // determine index informed by qubits outcome
+
3601  outcomeInd = 0;
+
3602  for (q=0; q<numQubits; q++)
+
3603  outcomeInd += extractBit(qubits[q], i + offset) * (1LL << q);
+
3604 
+
3605  prob = stateRe[i]*stateRe[i] + stateIm[i]*stateIm[i];
+
3606 
+
3607  // atomicly update corresponding outcome array element
+
3608  # ifdef _OPENMP
+
3609  # pragma omp atomic
+
3610  # endif
+
3611  outcomeProbs[outcomeInd] += prob;
+
3612  }
+
3613  }
+
3614 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_calcProbOfAllOutcomes().

+

Referenced by statevec_calcProbOfAllOutcomes().

@@ -2502,36 +2503,36 @@

Definition at line 3809 of file QuEST_cpu.c.

-
3810 {
-
3811  // ----- temp variables
-
3812  long long int thisTask;
-
3813  long long int numTasks=qureg.numAmpsPerChunk;
-
3814 
-
3815  qreal renorm=1/sqrt(totalProbability);
-
3816 
-
3817  qreal *stateVecReal = qureg.stateVec.real;
-
3818  qreal *stateVecImag = qureg.stateVec.imag;
-
3819 
-
3820 # ifdef _OPENMP
-
3821 # pragma omp parallel \
-
3822  shared (numTasks,stateVecReal,stateVecImag) \
-
3823  private (thisTask)
-
3824 # endif
-
3825  {
-
3826 # ifdef _OPENMP
-
3827 # pragma omp for schedule (static)
-
3828 # endif
-
3829  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3830  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
-
3831  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
-
3832  }
-
3833  }
-
3834 }
+

Definition at line 3849 of file QuEST_cpu.c.

+
3850 {
+
3851  // ----- temp variables
+
3852  long long int thisTask;
+
3853  long long int numTasks=qureg.numAmpsPerChunk;
+
3854 
+
3855  qreal renorm=1/sqrt(totalProbability);
+
3856 
+
3857  qreal *stateVecReal = qureg.stateVec.real;
+
3858  qreal *stateVecImag = qureg.stateVec.imag;
+
3859 
+
3860 # ifdef _OPENMP
+
3861 # pragma omp parallel \
+
3862  shared (numTasks,stateVecReal,stateVecImag) \
+
3863  private (thisTask)
+
3864 # endif
+
3865  {
+
3866 # ifdef _OPENMP
+
3867 # pragma omp for schedule (static)
+
3868 # endif
+
3869  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3870  stateVecReal[thisTask] = stateVecReal[thisTask]*renorm;
+
3871  stateVecImag[thisTask] = stateVecImag[thisTask]*renorm;
+
3872  }
+
3873  }
+
3874 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_collapseToKnownProbOutcome().

@@ -2585,76 +2586,76 @@

Definition at line 3727 of file QuEST_cpu.c.

-
3728 {
-
3729  // ----- sizes
-
3730  long long int sizeBlock, // size of blocks
-
3731  sizeHalfBlock; // size of blocks halved
-
3732  // ----- indices
-
3733  long long int thisBlock, // current block
-
3734  index; // current index for first half block
-
3735  // ----- measured probability
-
3736  qreal renorm; // probability (returned) value
-
3737  // ----- temp variables
-
3738  long long int thisTask; // task based approach for expose loop with small granularity
-
3739  // (good for shared memory parallelism)
-
3740  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3741 
-
3742  // ---------------------------------------------------------------- //
-
3743  // dimensions //
-
3744  // ---------------------------------------------------------------- //
-
3745  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3746  // and then the number to skip
-
3747  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3748 
-
3749  renorm=1/sqrt(totalProbability);
-
3750  qreal *stateVecReal = qureg.stateVec.real;
-
3751  qreal *stateVecImag = qureg.stateVec.imag;
-
3752 
-
3753 
-
3754 # ifdef _OPENMP
-
3755 # pragma omp parallel \
-
3756  default (none) \
-
3757  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
-
3758  private (thisTask,thisBlock,index)
-
3759 # endif
-
3760  {
-
3761  if (outcome==0){
-
3762  // measure qubit is 0
-
3763 # ifdef _OPENMP
-
3764 # pragma omp for schedule (static)
-
3765 # endif
-
3766  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3767  thisBlock = thisTask / sizeHalfBlock;
-
3768  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3769  stateVecReal[index]=stateVecReal[index]*renorm;
-
3770  stateVecImag[index]=stateVecImag[index]*renorm;
-
3771 
-
3772  stateVecReal[index+sizeHalfBlock]=0;
-
3773  stateVecImag[index+sizeHalfBlock]=0;
-
3774  }
-
3775  } else {
-
3776  // measure qubit is 1
-
3777 # ifdef _OPENMP
-
3778 # pragma omp for schedule (static)
-
3779 # endif
-
3780  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3781  thisBlock = thisTask / sizeHalfBlock;
-
3782  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3783  stateVecReal[index]=0;
-
3784  stateVecImag[index]=0;
-
3785 
-
3786  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
3787  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
3788  }
-
3789  }
-
3790  }
-
3791 
-
3792 }
+

Definition at line 3767 of file QuEST_cpu.c.

+
3768 {
+
3769  // ----- sizes
+
3770  long long int sizeBlock, // size of blocks
+
3771  sizeHalfBlock; // size of blocks halved
+
3772  // ----- indices
+
3773  long long int thisBlock, // current block
+
3774  index; // current index for first half block
+
3775  // ----- measured probability
+
3776  qreal renorm; // probability (returned) value
+
3777  // ----- temp variables
+
3778  long long int thisTask; // task based approach for expose loop with small granularity
+
3779  // (good for shared memory parallelism)
+
3780  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3781 
+
3782  // ---------------------------------------------------------------- //
+
3783  // dimensions //
+
3784  // ---------------------------------------------------------------- //
+
3785  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
3786  // and then the number to skip
+
3787  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
3788 
+
3789  renorm=1/sqrt(totalProbability);
+
3790  qreal *stateVecReal = qureg.stateVec.real;
+
3791  qreal *stateVecImag = qureg.stateVec.imag;
+
3792 
+
3793 
+
3794 # ifdef _OPENMP
+
3795 # pragma omp parallel \
+
3796  default (none) \
+
3797  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,renorm,outcome) \
+
3798  private (thisTask,thisBlock,index)
+
3799 # endif
+
3800  {
+
3801  if (outcome==0){
+
3802  // measure qubit is 0
+
3803 # ifdef _OPENMP
+
3804 # pragma omp for schedule (static)
+
3805 # endif
+
3806  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3807  thisBlock = thisTask / sizeHalfBlock;
+
3808  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3809  stateVecReal[index]=stateVecReal[index]*renorm;
+
3810  stateVecImag[index]=stateVecImag[index]*renorm;
+
3811 
+
3812  stateVecReal[index+sizeHalfBlock]=0;
+
3813  stateVecImag[index+sizeHalfBlock]=0;
+
3814  }
+
3815  } else {
+
3816  // measure qubit is 1
+
3817 # ifdef _OPENMP
+
3818 # pragma omp for schedule (static)
+
3819 # endif
+
3820  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3821  thisBlock = thisTask / sizeHalfBlock;
+
3822  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3823  stateVecReal[index]=0;
+
3824  stateVecImag[index]=0;
+
3825 
+
3826  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
+
3827  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
+
3828  }
+
3829  }
+
3830  }
+
3831 
+
3832 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_collapseToKnownProbOutcome().

@@ -2674,38 +2675,38 @@

-

Definition at line 3847 of file QuEST_cpu.c.

-
3848 {
-
3849  // ----- temp variables
-
3850  long long int thisTask;
-
3851  long long int numTasks=qureg.numAmpsPerChunk;
-
3852 
-
3853  // ---------------------------------------------------------------- //
-
3854  // find probability //
-
3855  // ---------------------------------------------------------------- //
-
3856 
-
3857  qreal *stateVecReal = qureg.stateVec.real;
-
3858  qreal *stateVecImag = qureg.stateVec.imag;
-
3859 
-
3860 # ifdef _OPENMP
-
3861 # pragma omp parallel \
-
3862  shared (numTasks,stateVecReal,stateVecImag) \
-
3863  private (thisTask)
-
3864 # endif
-
3865  {
-
3866 # ifdef _OPENMP
-
3867 # pragma omp for schedule (static)
-
3868 # endif
-
3869  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3870  stateVecReal[thisTask] = 0;
-
3871  stateVecImag[thisTask] = 0;
-
3872  }
-
3873  }
-
3874 }
+

Definition at line 3887 of file QuEST_cpu.c.

+
3888 {
+
3889  // ----- temp variables
+
3890  long long int thisTask;
+
3891  long long int numTasks=qureg.numAmpsPerChunk;
+
3892 
+
3893  // ---------------------------------------------------------------- //
+
3894  // find probability //
+
3895  // ---------------------------------------------------------------- //
+
3896 
+
3897  qreal *stateVecReal = qureg.stateVec.real;
+
3898  qreal *stateVecImag = qureg.stateVec.imag;
+
3899 
+
3900 # ifdef _OPENMP
+
3901 # pragma omp parallel \
+
3902  shared (numTasks,stateVecReal,stateVecImag) \
+
3903  private (thisTask)
+
3904 # endif
+
3905  {
+
3906 # ifdef _OPENMP
+
3907 # pragma omp for schedule (static)
+
3908 # endif
+
3909  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3910  stateVecReal[thisTask] = 0;
+
3911  stateVecImag[thisTask] = 0;
+
3912  }
+
3913  }
+
3914 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_collapseToKnownProbOutcome().

+

Referenced by statevec_collapseToKnownProbOutcome().

@@ -2772,48 +2773,48 @@

Definition at line 2056 of file QuEST_cpu.c.

-
2061 {
-
2062 
-
2063  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2064  long long int thisTask;
-
2065  long long int numTasks=qureg.numAmpsPerChunk;
-
2066 
-
2067  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2068  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2069  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2070  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2071  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2072 
-
2073 # ifdef _OPENMP
-
2074 # pragma omp parallel \
-
2075  default (none) \
-
2076  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2077  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
-
2078  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2079 # endif
-
2080  {
-
2081 # ifdef _OPENMP
-
2082 # pragma omp for schedule (static)
-
2083 # endif
-
2084  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2085  // store current state vector values in temp variables
-
2086  stateRealUp = stateVecRealUp[thisTask];
-
2087  stateImagUp = stateVecImagUp[thisTask];
-
2088 
-
2089  stateRealLo = stateVecRealLo[thisTask];
-
2090  stateImagLo = stateVecImagLo[thisTask];
-
2091 
-
2092  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2093  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2094  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2095  }
-
2096  }
-
2097 }
+

Definition at line 2095 of file QuEST_cpu.c.

+
2100 {
+
2101 
+
2102  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2103  long long int thisTask;
+
2104  long long int numTasks=qureg.numAmpsPerChunk;
+
2105 
+
2106  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2107  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2108  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2109  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2110  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2111 
+
2112 # ifdef _OPENMP
+
2113 # pragma omp parallel \
+
2114  default (none) \
+
2115  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2116  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks) \
+
2117  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2118 # endif
+
2119  {
+
2120 # ifdef _OPENMP
+
2121 # pragma omp for schedule (static)
+
2122 # endif
+
2123  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2124  // store current state vector values in temp variables
+
2125  stateRealUp = stateVecRealUp[thisTask];
+
2126  stateImagUp = stateVecImagUp[thisTask];
+
2127 
+
2128  stateRealLo = stateVecRealLo[thisTask];
+
2129  stateImagLo = stateVecImagLo[thisTask];
+
2130 
+
2131  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2132  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
+
2133  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
+
2134  }
+
2135  }
+
2136 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_compactUnitary().

+

Referenced by statevec_compactUnitary().

@@ -2855,68 +2856,68 @@

-

Definition at line 1743 of file QuEST_cpu.c.

-
1744 {
-
1745  long long int sizeBlock, sizeHalfBlock;
-
1746  long long int thisBlock, // current block
-
1747  indexUp,indexLo; // current index and corresponding index in lower half block
-
1748 
-
1749  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1750  long long int thisTask;
-
1751  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1752 
-
1753  // set dimensions
-
1754  sizeHalfBlock = 1LL << targetQubit;
-
1755  sizeBlock = 2LL * sizeHalfBlock;
-
1756 
-
1757  // Can't use qureg.stateVec as a private OMP var
-
1758  qreal *stateVecReal = qureg.stateVec.real;
-
1759  qreal *stateVecImag = qureg.stateVec.imag;
-
1760  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
1761  qreal betaImag=beta.imag, betaReal=beta.real;
-
1762 
-
1763 # ifdef _OPENMP
-
1764 # pragma omp parallel \
-
1765  default (none) \
-
1766  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
-
1767  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
1768 # endif
-
1769  {
-
1770 # ifdef _OPENMP
-
1771 # pragma omp for schedule (static)
-
1772 # endif
-
1773  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1774 
-
1775  thisBlock = thisTask / sizeHalfBlock;
-
1776  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1777  indexLo = indexUp + sizeHalfBlock;
-
1778 
-
1779  // store current state vector values in temp variables
-
1780  stateRealUp = stateVecReal[indexUp];
-
1781  stateImagUp = stateVecImag[indexUp];
-
1782 
-
1783  stateRealLo = stateVecReal[indexLo];
-
1784  stateImagLo = stateVecImag[indexLo];
+

Definition at line 1754 of file QuEST_cpu.c.

+
1755 {
+
1756  long long int sizeBlock, sizeHalfBlock;
+
1757  long long int thisBlock, // current block
+
1758  indexUp,indexLo; // current index and corresponding index in lower half block
+
1759 
+
1760  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
1761  long long int thisTask;
+
1762  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1763 
+
1764  // set dimensions
+
1765  sizeHalfBlock = 1LL << targetQubit;
+
1766  sizeBlock = 2LL * sizeHalfBlock;
+
1767 
+
1768  // Can't use qureg.stateVec as a private OMP var
+
1769  qreal *stateVecReal = qureg.stateVec.real;
+
1770  qreal *stateVecImag = qureg.stateVec.imag;
+
1771  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
1772  qreal betaImag=beta.imag, betaReal=beta.real;
+
1773 
+
1774 # ifdef _OPENMP
+
1775 # pragma omp parallel \
+
1776  default (none) \
+
1777  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, numTasks) \
+
1778  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
1779 # endif
+
1780  {
+
1781 # ifdef _OPENMP
+
1782 # pragma omp for schedule (static)
+
1783 # endif
+
1784  for (thisTask=0; thisTask<numTasks; thisTask++) {
1785 
-
1786  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
1787  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
1788  - betaReal*stateRealLo - betaImag*stateImagLo;
-
1789  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
1790  - betaReal*stateImagLo + betaImag*stateRealLo;
-
1791 
-
1792  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
1793  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
1794  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
1795  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
1796  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
1797  }
-
1798  }
-
1799 
-
1800 }
+
1786  thisBlock = thisTask / sizeHalfBlock;
+
1787  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1788  indexLo = indexUp + sizeHalfBlock;
+
1789 
+
1790  // store current state vector values in temp variables
+
1791  stateRealUp = stateVecReal[indexUp];
+
1792  stateImagUp = stateVecImag[indexUp];
+
1793 
+
1794  stateRealLo = stateVecReal[indexLo];
+
1795  stateImagLo = stateVecImag[indexLo];
+
1796 
+
1797  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
1798  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
1799  - betaReal*stateRealLo - betaImag*stateImagLo;
+
1800  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
1801  - betaReal*stateImagLo + betaImag*stateRealLo;
+
1802 
+
1803  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
1804  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
1805  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
1806  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
1807  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
1808  }
+
1809  }
+
1810 
+
1811 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

-

Referenced by statevec_compactUnitary().

+

Referenced by statevec_compactUnitary().

@@ -2991,55 +2992,55 @@

Definition at line 2375 of file QuEST_cpu.c.

-
2380 {
-
2381 
-
2382  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2383  long long int thisTask;
-
2384  long long int numTasks=qureg.numAmpsPerChunk;
-
2385  long long int chunkSize=qureg.numAmpsPerChunk;
-
2386  long long int chunkId=qureg.chunkId;
-
2387 
-
2388  int controlBit;
-
2389 
-
2390  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2391  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2392  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2393  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2394  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2395 
-
2396 # ifdef _OPENMP
-
2397 # pragma omp parallel \
-
2398  default (none) \
-
2399  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2400  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
-
2401  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2402 # endif
-
2403  {
-
2404 # ifdef _OPENMP
-
2405 # pragma omp for schedule (static)
-
2406 # endif
-
2407  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2408  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2409  if (controlBit){
-
2410  // store current state vector values in temp variables
-
2411  stateRealUp = stateVecRealUp[thisTask];
-
2412  stateImagUp = stateVecImagUp[thisTask];
-
2413 
-
2414  stateRealLo = stateVecRealLo[thisTask];
-
2415  stateImagLo = stateVecImagLo[thisTask];
-
2416 
-
2417  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2418  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
-
2419  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
-
2420  }
-
2421  }
-
2422  }
-
2423 }
+

Definition at line 2414 of file QuEST_cpu.c.

+
2419 {
+
2420 
+
2421  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2422  long long int thisTask;
+
2423  long long int numTasks=qureg.numAmpsPerChunk;
+
2424  long long int chunkSize=qureg.numAmpsPerChunk;
+
2425  long long int chunkId=qureg.chunkId;
+
2426 
+
2427  int controlBit;
+
2428 
+
2429  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2430  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2431  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2432  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2433  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2434 
+
2435 # ifdef _OPENMP
+
2436 # pragma omp parallel \
+
2437  default (none) \
+
2438  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2439  rot1Real,rot1Imag, rot2Real,rot2Imag,numTasks,chunkId,chunkSize,controlQubit) \
+
2440  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2441 # endif
+
2442  {
+
2443 # ifdef _OPENMP
+
2444 # pragma omp for schedule (static)
+
2445 # endif
+
2446  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2447  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2448  if (controlBit){
+
2449  // store current state vector values in temp variables
+
2450  stateRealUp = stateVecRealUp[thisTask];
+
2451  stateImagUp = stateVecImagUp[thisTask];
+
2452 
+
2453  stateRealLo = stateVecRealLo[thisTask];
+
2454  stateImagLo = stateVecImagLo[thisTask];
+
2455 
+
2456  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2457  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp + rot2Real*stateRealLo + rot2Imag*stateImagLo;
+
2458  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp + rot2Real*stateImagLo - rot2Imag*stateRealLo;
+
2459  }
+
2460  }
+
2461  }
+
2462 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_controlledCompactUnitary().

+

Referenced by statevec_controlledCompactUnitary().

@@ -3087,76 +3088,76 @@

-

Definition at line 2157 of file QuEST_cpu.c.

-
2159 {
-
2160  long long int sizeBlock, sizeHalfBlock;
-
2161  long long int thisBlock, // current block
-
2162  indexUp,indexLo; // current index and corresponding index in lower half block
-
2163 
-
2164  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2165  long long int thisTask;
-
2166  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2167  long long int chunkSize=qureg.numAmpsPerChunk;
-
2168  long long int chunkId=qureg.chunkId;
-
2169 
-
2170  int controlBit;
-
2171 
-
2172  // set dimensions
-
2173  sizeHalfBlock = 1LL << targetQubit;
-
2174  sizeBlock = 2LL * sizeHalfBlock;
-
2175 
-
2176  // Can't use qureg.stateVec as a private OMP var
-
2177  qreal *stateVecReal = qureg.stateVec.real;
-
2178  qreal *stateVecImag = qureg.stateVec.imag;
-
2179  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
2180  qreal betaImag=beta.imag, betaReal=beta.real;
-
2181 
-
2182 # ifdef _OPENMP
-
2183 # pragma omp parallel \
-
2184  default (none) \
-
2185  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
-
2186  numTasks,chunkId,chunkSize,controlQubit) \
-
2187  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2188 # endif
-
2189  {
-
2190 # ifdef _OPENMP
-
2191 # pragma omp for schedule (static)
-
2192 # endif
-
2193  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2194 
-
2195  thisBlock = thisTask / sizeHalfBlock;
-
2196  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2197  indexLo = indexUp + sizeHalfBlock;
-
2198 
-
2199  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2200  if (controlBit){
-
2201  // store current state vector values in temp variables
-
2202  stateRealUp = stateVecReal[indexUp];
-
2203  stateImagUp = stateVecImag[indexUp];
-
2204 
-
2205  stateRealLo = stateVecReal[indexLo];
-
2206  stateImagLo = stateVecImag[indexLo];
-
2207 
-
2208  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
2209  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
2210  - betaReal*stateRealLo - betaImag*stateImagLo;
-
2211  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
2212  - betaReal*stateImagLo + betaImag*stateRealLo;
-
2213 
-
2214  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
2215  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
2216  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
2217  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
2218  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
2219  }
-
2220  }
-
2221  }
-
2222 
-
2223 }
+

Definition at line 2196 of file QuEST_cpu.c.

+
2198 {
+
2199  long long int sizeBlock, sizeHalfBlock;
+
2200  long long int thisBlock, // current block
+
2201  indexUp,indexLo; // current index and corresponding index in lower half block
+
2202 
+
2203  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2204  long long int thisTask;
+
2205  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2206  long long int chunkSize=qureg.numAmpsPerChunk;
+
2207  long long int chunkId=qureg.chunkId;
+
2208 
+
2209  int controlBit;
+
2210 
+
2211  // set dimensions
+
2212  sizeHalfBlock = 1LL << targetQubit;
+
2213  sizeBlock = 2LL * sizeHalfBlock;
+
2214 
+
2215  // Can't use qureg.stateVec as a private OMP var
+
2216  qreal *stateVecReal = qureg.stateVec.real;
+
2217  qreal *stateVecImag = qureg.stateVec.imag;
+
2218  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
2219  qreal betaImag=beta.imag, betaReal=beta.real;
+
2220 
+
2221 # ifdef _OPENMP
+
2222 # pragma omp parallel \
+
2223  default (none) \
+
2224  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, alphaReal,alphaImag, betaReal,betaImag, \
+
2225  numTasks,chunkId,chunkSize,controlQubit) \
+
2226  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2227 # endif
+
2228  {
+
2229 # ifdef _OPENMP
+
2230 # pragma omp for schedule (static)
+
2231 # endif
+
2232  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2233 
+
2234  thisBlock = thisTask / sizeHalfBlock;
+
2235  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2236  indexLo = indexUp + sizeHalfBlock;
+
2237 
+
2238  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
+
2239  if (controlBit){
+
2240  // store current state vector values in temp variables
+
2241  stateRealUp = stateVecReal[indexUp];
+
2242  stateImagUp = stateVecImag[indexUp];
+
2243 
+
2244  stateRealLo = stateVecReal[indexLo];
+
2245  stateImagLo = stateVecImag[indexLo];
+
2246 
+
2247  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
2248  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
2249  - betaReal*stateRealLo - betaImag*stateImagLo;
+
2250  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
2251  - betaReal*stateImagLo + betaImag*stateRealLo;
+
2252 
+
2253  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
2254  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
2255  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
2256  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
2257  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
2258  }
+
2259  }
+
2260  }
+
2261 
+
2262 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

-

Referenced by statevec_controlledCompactUnitary().

+

Referenced by statevec_controlledCompactUnitary().

@@ -3210,43 +3211,43 @@

Definition at line 2703 of file QuEST_cpu.c.

-
2706 {
-
2707 
-
2708  long long int thisTask;
-
2709  long long int numTasks=qureg.numAmpsPerChunk;
-
2710  long long int chunkSize=qureg.numAmpsPerChunk;
-
2711  long long int chunkId=qureg.chunkId;
-
2712 
-
2713  int controlBit;
-
2714 
-
2715  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2716  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2717 
-
2718 # ifdef _OPENMP
-
2719 # pragma omp parallel \
-
2720  default (none) \
-
2721  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2722  numTasks,chunkId,chunkSize,controlQubit) \
-
2723  private (thisTask,controlBit)
-
2724 # endif
-
2725  {
-
2726 # ifdef _OPENMP
-
2727 # pragma omp for schedule (static)
-
2728 # endif
-
2729  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2730  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2731  if (controlBit){
-
2732  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2733  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2734  }
-
2735  }
-
2736  }
-
2737 }
+

Definition at line 2742 of file QuEST_cpu.c.

+
2745 {
+
2746 
+
2747  long long int thisTask;
+
2748  long long int numTasks=qureg.numAmpsPerChunk;
+
2749  long long int chunkSize=qureg.numAmpsPerChunk;
+
2750  long long int chunkId=qureg.chunkId;
+
2751 
+
2752  int controlBit;
+
2753 
+
2754  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2755  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2756 
+
2757 # ifdef _OPENMP
+
2758 # pragma omp parallel \
+
2759  default (none) \
+
2760  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
2761  numTasks,chunkId,chunkSize,controlQubit) \
+
2762  private (thisTask,controlBit)
+
2763 # endif
+
2764  {
+
2765 # ifdef _OPENMP
+
2766 # pragma omp for schedule (static)
+
2767 # endif
+
2768  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2769  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2770  if (controlBit){
+
2771  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
+
2772  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
+
2773  }
+
2774  }
+
2775  }
+
2776 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_controlledNot().

+

Referenced by statevec_controlledNot().

@@ -3282,61 +3283,61 @@

-

Definition at line 2640 of file QuEST_cpu.c.

-
2641 {
-
2642  long long int sizeBlock, sizeHalfBlock;
-
2643  long long int thisBlock, // current block
-
2644  indexUp,indexLo; // current index and corresponding index in lower half block
-
2645 
-
2646  qreal stateRealUp,stateImagUp;
-
2647  long long int thisTask;
-
2648  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2649  long long int chunkSize=qureg.numAmpsPerChunk;
-
2650  long long int chunkId=qureg.chunkId;
-
2651 
-
2652  int controlBit;
-
2653 
-
2654  // set dimensions
-
2655  sizeHalfBlock = 1LL << targetQubit;
-
2656  sizeBlock = 2LL * sizeHalfBlock;
-
2657 
-
2658  // Can't use qureg.stateVec as a private OMP var
-
2659  qreal *stateVecReal = qureg.stateVec.real;
-
2660  qreal *stateVecImag = qureg.stateVec.imag;
-
2661 
-
2662 # ifdef _OPENMP
-
2663 # pragma omp parallel \
-
2664  default (none) \
-
2665  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
-
2666  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2667 # endif
-
2668  {
-
2669 # ifdef _OPENMP
-
2670 # pragma omp for schedule (static)
-
2671 # endif
-
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2673  thisBlock = thisTask / sizeHalfBlock;
-
2674  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2675  indexLo = indexUp + sizeHalfBlock;
-
2676 
-
2677  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2678  if (controlBit){
-
2679  stateRealUp = stateVecReal[indexUp];
-
2680  stateImagUp = stateVecImag[indexUp];
-
2681 
-
2682  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2683  stateVecImag[indexUp] = stateVecImag[indexLo];
+

Definition at line 2679 of file QuEST_cpu.c.

+
2680 {
+
2681  long long int sizeBlock, sizeHalfBlock;
+
2682  long long int thisBlock, // current block
+
2683  indexUp,indexLo; // current index and corresponding index in lower half block
2684 
-
2685  stateVecReal[indexLo] = stateRealUp;
-
2686  stateVecImag[indexLo] = stateImagUp;
-
2687  }
-
2688  }
-
2689  }
-
2690 }
+
2685  qreal stateRealUp,stateImagUp;
+
2686  long long int thisTask;
+
2687  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2688  long long int chunkSize=qureg.numAmpsPerChunk;
+
2689  long long int chunkId=qureg.chunkId;
+
2690 
+
2691  int controlBit;
+
2692 
+
2693  // set dimensions
+
2694  sizeHalfBlock = 1LL << targetQubit;
+
2695  sizeBlock = 2LL * sizeHalfBlock;
+
2696 
+
2697  // Can't use qureg.stateVec as a private OMP var
+
2698  qreal *stateVecReal = qureg.stateVec.real;
+
2699  qreal *stateVecImag = qureg.stateVec.imag;
+
2700 
+
2701 # ifdef _OPENMP
+
2702 # pragma omp parallel \
+
2703  default (none) \
+
2704  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag,numTasks,chunkId,chunkSize,controlQubit) \
+
2705  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
2706 # endif
+
2707  {
+
2708 # ifdef _OPENMP
+
2709 # pragma omp for schedule (static)
+
2710 # endif
+
2711  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2712  thisBlock = thisTask / sizeHalfBlock;
+
2713  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2714  indexLo = indexUp + sizeHalfBlock;
+
2715 
+
2716  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
+
2717  if (controlBit){
+
2718  stateRealUp = stateVecReal[indexUp];
+
2719  stateImagUp = stateVecImag[indexUp];
+
2720 
+
2721  stateVecReal[indexUp] = stateVecReal[indexLo];
+
2722  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2723 
+
2724  stateVecReal[indexLo] = stateRealUp;
+
2725  stateVecImag[indexLo] = stateImagUp;
+
2726  }
+
2727  }
+
2728  }
+
2729 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_controlledNot().

+

Referenced by statevec_controlledNot().

@@ -3384,43 +3385,43 @@

-

Definition at line 2997 of file QuEST_cpu.c.

-
3000 {
-
3001 
-
3002  long long int thisTask;
-
3003  long long int numTasks=qureg.numAmpsPerChunk;
-
3004  long long int chunkSize=qureg.numAmpsPerChunk;
-
3005  long long int chunkId=qureg.chunkId;
-
3006 
-
3007  int controlBit;
-
3008 
-
3009  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
3010  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
3011 
-
3012 # ifdef _OPENMP
-
3013 # pragma omp parallel \
-
3014  default (none) \
-
3015  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
3016  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
-
3017  private (thisTask,controlBit)
-
3018 # endif
-
3019  {
-
3020 # ifdef _OPENMP
-
3021 # pragma omp for schedule (static)
-
3022 # endif
-
3023  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3024  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
3025  if (controlBit){
-
3026  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
-
3027  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
-
3028  }
-
3029  }
-
3030  }
-
3031 }
+

Definition at line 3036 of file QuEST_cpu.c.

+
3039 {
+
3040 
+
3041  long long int thisTask;
+
3042  long long int numTasks=qureg.numAmpsPerChunk;
+
3043  long long int chunkSize=qureg.numAmpsPerChunk;
+
3044  long long int chunkId=qureg.chunkId;
+
3045 
+
3046  int controlBit;
+
3047 
+
3048  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
3049  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
3050 
+
3051 # ifdef _OPENMP
+
3052 # pragma omp parallel \
+
3053  default (none) \
+
3054  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
3055  numTasks,chunkId,chunkSize,controlQubit,conjFac) \
+
3056  private (thisTask,controlBit)
+
3057 # endif
+
3058  {
+
3059 # ifdef _OPENMP
+
3060 # pragma omp for schedule (static)
+
3061 # endif
+
3062  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3063  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
3064  if (controlBit){
+
3065  stateVecRealOut[thisTask] = conjFac * stateVecImagIn[thisTask];
+
3066  stateVecImagOut[thisTask] = conjFac * -stateVecRealIn[thisTask];
+
3067  }
+
3068  }
+
3069  }
+
3070 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

+

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

@@ -3462,62 +3463,62 @@

-

Definition at line 2943 of file QuEST_cpu.c.

-
2944 {
-
2945  long long int sizeBlock, sizeHalfBlock;
-
2946  long long int thisBlock, // current block
-
2947  indexUp,indexLo; // current index and corresponding index in lower half block
-
2948 
-
2949  qreal stateRealUp,stateImagUp;
-
2950  long long int thisTask;
-
2951  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2952  long long int chunkSize=qureg.numAmpsPerChunk;
-
2953  long long int chunkId=qureg.chunkId;
-
2954 
-
2955  int controlBit;
-
2956 
-
2957  // set dimensions
-
2958  sizeHalfBlock = 1LL << targetQubit;
-
2959  sizeBlock = 2LL * sizeHalfBlock;
-
2960 
-
2961  // Can't use qureg.stateVec as a private OMP var
-
2962  qreal *stateVecReal = qureg.stateVec.real;
-
2963  qreal *stateVecImag = qureg.stateVec.imag;
-
2964 
-
2965 # ifdef _OPENMP
-
2966 # pragma omp parallel \
-
2967  default (none) \
-
2968  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
-
2969  chunkSize,controlQubit,conjFac) \
-
2970  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
-
2971 # endif
-
2972  {
-
2973 # ifdef _OPENMP
-
2974 # pragma omp for schedule (static)
-
2975 # endif
-
2976  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2977  thisBlock = thisTask / sizeHalfBlock;
-
2978  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2979  indexLo = indexUp + sizeHalfBlock;
-
2980 
-
2981  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
-
2982  if (controlBit){
-
2983  stateRealUp = stateVecReal[indexUp];
-
2984  stateImagUp = stateVecImag[indexUp];
-
2985 
-
2986  // update under +-{{0, -i}, {i, 0}}
-
2987  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2988  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2989  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2990  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2991  }
-
2992  }
-
2993  }
-
2994 }
+

Definition at line 2982 of file QuEST_cpu.c.

+
2983 {
+
2984  long long int sizeBlock, sizeHalfBlock;
+
2985  long long int thisBlock, // current block
+
2986  indexUp,indexLo; // current index and corresponding index in lower half block
+
2987 
+
2988  qreal stateRealUp,stateImagUp;
+
2989  long long int thisTask;
+
2990  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2991  long long int chunkSize=qureg.numAmpsPerChunk;
+
2992  long long int chunkId=qureg.chunkId;
+
2993 
+
2994  int controlBit;
+
2995 
+
2996  // set dimensions
+
2997  sizeHalfBlock = 1LL << targetQubit;
+
2998  sizeBlock = 2LL * sizeHalfBlock;
+
2999 
+
3000  // Can't use qureg.stateVec as a private OMP var
+
3001  qreal *stateVecReal = qureg.stateVec.real;
+
3002  qreal *stateVecImag = qureg.stateVec.imag;
+
3003 
+
3004 # ifdef _OPENMP
+
3005 # pragma omp parallel \
+
3006  default (none) \
+
3007  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,chunkId, \
+
3008  chunkSize,controlQubit,conjFac) \
+
3009  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,controlBit)
+
3010 # endif
+
3011  {
+
3012 # ifdef _OPENMP
+
3013 # pragma omp for schedule (static)
+
3014 # endif
+
3015  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3016  thisBlock = thisTask / sizeHalfBlock;
+
3017  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3018  indexLo = indexUp + sizeHalfBlock;
+
3019 
+
3020  controlBit = extractBit(controlQubit, indexUp+chunkId*chunkSize);
+
3021  if (controlBit){
+
3022  stateRealUp = stateVecReal[indexUp];
+
3023  stateImagUp = stateVecImag[indexUp];
+
3024 
+
3025  // update under +-{{0, -i}, {i, 0}}
+
3026  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
3027  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
3028  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
3029  stateVecImag[indexLo] = conjFac * stateRealUp;
+
3030  }
+
3031  }
+
3032  }
+
3033 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

+

Referenced by statevec_controlledPauliY(), and statevec_controlledPauliYConj().

@@ -3592,56 +3593,56 @@

Definition at line 2437 of file QuEST_cpu.c.

-
2442 {
-
2443 
-
2444  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2445  long long int thisTask;
-
2446  long long int numTasks=qureg.numAmpsPerChunk;
-
2447  long long int chunkSize=qureg.numAmpsPerChunk;
-
2448  long long int chunkId=qureg.chunkId;
-
2449 
-
2450  int controlBit;
-
2451 
-
2452  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2453  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2454  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2455  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2456  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2457 
-
2458 # ifdef _OPENMP
-
2459 # pragma omp parallel \
-
2460  default (none) \
-
2461  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2462  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
-
2463  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2464 # endif
-
2465  {
-
2466 # ifdef _OPENMP
-
2467 # pragma omp for schedule (static)
-
2468 # endif
-
2469  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2470  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
-
2471  if (controlBit){
-
2472  // store current state vector values in temp variables
-
2473  stateRealUp = stateVecRealUp[thisTask];
-
2474  stateImagUp = stateVecImagUp[thisTask];
-
2475 
-
2476  stateRealLo = stateVecRealLo[thisTask];
-
2477  stateImagLo = stateVecImagLo[thisTask];
-
2478 
-
2479  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2480  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2481  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2482  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2483  }
-
2484  }
-
2485  }
-
2486 }
+

Definition at line 2476 of file QuEST_cpu.c.

+
2481 {
+
2482 
+
2483  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2484  long long int thisTask;
+
2485  long long int numTasks=qureg.numAmpsPerChunk;
+
2486  long long int chunkSize=qureg.numAmpsPerChunk;
+
2487  long long int chunkId=qureg.chunkId;
+
2488 
+
2489  int controlBit;
+
2490 
+
2491  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2492  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2493  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2494  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2495  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2496 
+
2497 # ifdef _OPENMP
+
2498 # pragma omp parallel \
+
2499  default (none) \
+
2500  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2501  rot1Real,rot1Imag, rot2Real,rot2Imag, numTasks,chunkId,chunkSize,controlQubit) \
+
2502  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2503 # endif
+
2504  {
+
2505 # ifdef _OPENMP
+
2506 # pragma omp for schedule (static)
+
2507 # endif
+
2508  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2509  controlBit = extractBit (controlQubit, thisTask+chunkId*chunkSize);
+
2510  if (controlBit){
+
2511  // store current state vector values in temp variables
+
2512  stateRealUp = stateVecRealUp[thisTask];
+
2513  stateImagUp = stateVecImagUp[thisTask];
+
2514 
+
2515  stateRealLo = stateVecRealLo[thisTask];
+
2516  stateImagLo = stateVecImagLo[thisTask];
+
2517 
+
2518  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2519  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2520  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2521  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2522  }
+
2523  }
+
2524  }
+
2525 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_controlledUnitary().

+

Referenced by statevec_controlledUnitary().

@@ -3683,74 +3684,74 @@

-

Definition at line 2297 of file QuEST_cpu.c.

-
2299 {
-
2300  long long int sizeBlock, sizeHalfBlock;
-
2301  long long int thisBlock, // current block
-
2302  indexUp,indexLo; // current index and corresponding index in lower half block
-
2303 
-
2304  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2305  long long int thisTask;
-
2306  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2307  long long int chunkSize=qureg.numAmpsPerChunk;
-
2308  long long int chunkId=qureg.chunkId;
-
2309 
-
2310  int controlBit;
-
2311 
-
2312  // set dimensions
-
2313  sizeHalfBlock = 1LL << targetQubit;
-
2314  sizeBlock = 2LL * sizeHalfBlock;
-
2315 
-
2316  // Can't use qureg.stateVec as a private OMP var
-
2317  qreal *stateVecReal = qureg.stateVec.real;
-
2318  qreal *stateVecImag = qureg.stateVec.imag;
-
2319 
-
2320 # ifdef _OPENMP
-
2321 # pragma omp parallel \
-
2322  default (none) \
-
2323  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
-
2324  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
-
2325 # endif
-
2326  {
-
2327 # ifdef _OPENMP
-
2328 # pragma omp for schedule (static)
-
2329 # endif
-
2330  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2331 
-
2332  thisBlock = thisTask / sizeHalfBlock;
-
2333  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2334  indexLo = indexUp + sizeHalfBlock;
-
2335 
-
2336  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
-
2337  if (controlBit){
-
2338  // store current state vector values in temp variables
-
2339  stateRealUp = stateVecReal[indexUp];
-
2340  stateImagUp = stateVecImag[indexUp];
-
2341 
-
2342  stateRealLo = stateVecReal[indexLo];
-
2343  stateImagLo = stateVecImag[indexLo];
-
2344 
-
2345 
-
2346  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2347  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2348  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2349  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2350  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2351 
-
2352  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2353  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2354  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2355  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2356  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2357  }
-
2358  }
-
2359  }
-
2360 
-
2361 }
+

Definition at line 2336 of file QuEST_cpu.c.

+
2338 {
+
2339  long long int sizeBlock, sizeHalfBlock;
+
2340  long long int thisBlock, // current block
+
2341  indexUp,indexLo; // current index and corresponding index in lower half block
+
2342 
+
2343  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2344  long long int thisTask;
+
2345  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2346  long long int chunkSize=qureg.numAmpsPerChunk;
+
2347  long long int chunkId=qureg.chunkId;
+
2348 
+
2349  int controlBit;
+
2350 
+
2351  // set dimensions
+
2352  sizeHalfBlock = 1LL << targetQubit;
+
2353  sizeBlock = 2LL * sizeHalfBlock;
+
2354 
+
2355  // Can't use qureg.stateVec as a private OMP var
+
2356  qreal *stateVecReal = qureg.stateVec.real;
+
2357  qreal *stateVecImag = qureg.stateVec.imag;
+
2358 
+
2359 # ifdef _OPENMP
+
2360 # pragma omp parallel \
+
2361  default (none) \
+
2362  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks,chunkId,chunkSize,controlQubit) \
+
2363  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo,controlBit)
+
2364 # endif
+
2365  {
+
2366 # ifdef _OPENMP
+
2367 # pragma omp for schedule (static)
+
2368 # endif
+
2369  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2370 
+
2371  thisBlock = thisTask / sizeHalfBlock;
+
2372  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2373  indexLo = indexUp + sizeHalfBlock;
+
2374 
+
2375  controlBit = extractBit (controlQubit, indexUp+chunkId*chunkSize);
+
2376  if (controlBit){
+
2377  // store current state vector values in temp variables
+
2378  stateRealUp = stateVecReal[indexUp];
+
2379  stateImagUp = stateVecImag[indexUp];
+
2380 
+
2381  stateRealLo = stateVecReal[indexLo];
+
2382  stateImagLo = stateVecImag[indexLo];
+
2383 
+
2384 
+
2385  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2386  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2387  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2388  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2389  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2390 
+
2391  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2392  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2393  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2394  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2395  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2396  }
+
2397  }
+
2398  }
+
2399 
+
2400 }

References Qureg::chunkId, extractBit(), ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

-

Referenced by statevec_controlledUnitary().

+

Referenced by statevec_controlledUnitary().

@@ -3780,46 +3781,46 @@

Returns
probability of qubit measureQubit being zero
-

Definition at line 3474 of file QuEST_cpu.c.

-
3474  {
-
3475  // ----- measured probability
-
3476  qreal totalProbability; // probability (returned) value
-
3477  // ----- temp variables
-
3478  long long int thisTask; // task based approach for expose loop with small granularity
-
3479  long long int numTasks=qureg.numAmpsPerChunk;
-
3480 
-
3481  // ---------------------------------------------------------------- //
-
3482  // find probability //
-
3483  // ---------------------------------------------------------------- //
-
3484 
-
3485  // initialise returned value
-
3486  totalProbability = 0.0;
-
3487 
-
3488  qreal *stateVecReal = qureg.stateVec.real;
-
3489  qreal *stateVecImag = qureg.stateVec.imag;
-
3490 
-
3491 # ifdef _OPENMP
-
3492 # pragma omp parallel \
-
3493  shared (numTasks,stateVecReal,stateVecImag) \
-
3494  private (thisTask) \
-
3495  reduction ( +:totalProbability )
-
3496 # endif
-
3497  {
-
3498 # ifdef _OPENMP
-
3499 # pragma omp for schedule (static)
-
3500 # endif
-
3501  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3502  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
-
3503  + stateVecImag[thisTask]*stateVecImag[thisTask];
-
3504  }
-
3505  }
-
3506 
-
3507  return totalProbability;
-
3508 }
+

Definition at line 3513 of file QuEST_cpu.c.

+
3513  {
+
3514  // ----- measured probability
+
3515  qreal totalProbability; // probability (returned) value
+
3516  // ----- temp variables
+
3517  long long int thisTask; // task based approach for expose loop with small granularity
+
3518  long long int numTasks=qureg.numAmpsPerChunk;
+
3519 
+
3520  // ---------------------------------------------------------------- //
+
3521  // find probability //
+
3522  // ---------------------------------------------------------------- //
+
3523 
+
3524  // initialise returned value
+
3525  totalProbability = 0.0;
+
3526 
+
3527  qreal *stateVecReal = qureg.stateVec.real;
+
3528  qreal *stateVecImag = qureg.stateVec.imag;
+
3529 
+
3530 # ifdef _OPENMP
+
3531 # pragma omp parallel \
+
3532  shared (numTasks,stateVecReal,stateVecImag) \
+
3533  private (thisTask) \
+
3534  reduction ( +:totalProbability )
+
3535 # endif
+
3536  {
+
3537 # ifdef _OPENMP
+
3538 # pragma omp for schedule (static)
+
3539 # endif
+
3540  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3541  totalProbability += stateVecReal[thisTask]*stateVecReal[thisTask]
+
3542  + stateVecImag[thisTask]*stateVecImag[thisTask];
+
3543  }
+
3544  }
+
3545 
+
3546  return totalProbability;
+
3547 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_calcProbOfOutcome().

+

Referenced by statevec_calcProbOfOutcome().

@@ -3861,57 +3862,57 @@

Returns
probability of qubit measureQubit being zero
-

Definition at line 3418 of file QuEST_cpu.c.

-
3420 {
-
3421  // ----- sizes
-
3422  long long int sizeBlock, // size of blocks
-
3423  sizeHalfBlock; // size of blocks halved
-
3424  // ----- indices
-
3425  long long int thisBlock, // current block
-
3426  index; // current index for first half block
-
3427  // ----- measured probability
-
3428  qreal totalProbability; // probability (returned) value
-
3429  // ----- temp variables
-
3430  long long int thisTask;
-
3431  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3432 
-
3433  // ---------------------------------------------------------------- //
-
3434  // dimensions //
-
3435  // ---------------------------------------------------------------- //
-
3436  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
3437  // and then the number to skip
-
3438  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
3439 
-
3440  // initialise returned value
-
3441  totalProbability = 0.0;
-
3442 
-
3443  qreal *stateVecReal = qureg.stateVec.real;
-
3444  qreal *stateVecImag = qureg.stateVec.imag;
-
3445 
-
3446 # ifdef _OPENMP
-
3447 # pragma omp parallel \
-
3448  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
-
3449  private (thisTask,thisBlock,index) \
-
3450  reduction ( +:totalProbability )
-
3451 # endif
-
3452  {
-
3453 # ifdef _OPENMP
-
3454 # pragma omp for schedule (static)
-
3455 # endif
-
3456  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3457  thisBlock = thisTask / sizeHalfBlock;
-
3458  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3459 
-
3460  totalProbability += stateVecReal[index]*stateVecReal[index]
-
3461  + stateVecImag[index]*stateVecImag[index];
-
3462  }
-
3463  }
-
3464  return totalProbability;
-
3465 }
+

Definition at line 3457 of file QuEST_cpu.c.

+
3459 {
+
3460  // ----- sizes
+
3461  long long int sizeBlock, // size of blocks
+
3462  sizeHalfBlock; // size of blocks halved
+
3463  // ----- indices
+
3464  long long int thisBlock, // current block
+
3465  index; // current index for first half block
+
3466  // ----- measured probability
+
3467  qreal totalProbability; // probability (returned) value
+
3468  // ----- temp variables
+
3469  long long int thisTask;
+
3470  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3471 
+
3472  // ---------------------------------------------------------------- //
+
3473  // dimensions //
+
3474  // ---------------------------------------------------------------- //
+
3475  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
3476  // and then the number to skip
+
3477  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
3478 
+
3479  // initialise returned value
+
3480  totalProbability = 0.0;
+
3481 
+
3482  qreal *stateVecReal = qureg.stateVec.real;
+
3483  qreal *stateVecImag = qureg.stateVec.imag;
+
3484 
+
3485 # ifdef _OPENMP
+
3486 # pragma omp parallel \
+
3487  shared (numTasks,sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag) \
+
3488  private (thisTask,thisBlock,index) \
+
3489  reduction ( +:totalProbability )
+
3490 # endif
+
3491  {
+
3492 # ifdef _OPENMP
+
3493 # pragma omp for schedule (static)
+
3494 # endif
+
3495  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3496  thisBlock = thisTask / sizeHalfBlock;
+
3497  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3498 
+
3499  totalProbability += stateVecReal[index]*stateVecReal[index]
+
3500  + stateVecImag[index]*stateVecImag[index];
+
3501  }
+
3502  }
+
3503  return totalProbability;
+
3504 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_calcProbOfOutcome().

+

Referenced by statevec_calcProbOfOutcome().

@@ -3972,51 +3973,51 @@

Definition at line 3100 of file QuEST_cpu.c.

-
3105 {
-
3106 
-
3107  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
3108  long long int thisTask;
-
3109  long long int numTasks=qureg.numAmpsPerChunk;
-
3110 
-
3111  int sign;
-
3112  if (updateUpper) sign=1;
-
3113  else sign=-1;
-
3114 
-
3115  qreal recRoot2 = 1.0/sqrt(2);
-
3116 
-
3117  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
3118  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
3119  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
3120 
-
3121 # ifdef _OPENMP
-
3122 # pragma omp parallel \
-
3123  default (none) \
-
3124  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
3125  recRoot2, sign, numTasks) \
-
3126  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
3127 # endif
-
3128  {
-
3129 # ifdef _OPENMP
-
3130 # pragma omp for schedule (static)
-
3131 # endif
-
3132  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3133  // store current state vector values in temp variables
-
3134  stateRealUp = stateVecRealUp[thisTask];
-
3135  stateImagUp = stateVecImagUp[thisTask];
-
3136 
-
3137  stateRealLo = stateVecRealLo[thisTask];
-
3138  stateImagLo = stateVecImagLo[thisTask];
-
3139 
-
3140  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
-
3141  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
-
3142  }
-
3143  }
-
3144 }
+

Definition at line 3139 of file QuEST_cpu.c.

+
3144 {
+
3145 
+
3146  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
3147  long long int thisTask;
+
3148  long long int numTasks=qureg.numAmpsPerChunk;
+
3149 
+
3150  int sign;
+
3151  if (updateUpper) sign=1;
+
3152  else sign=-1;
+
3153 
+
3154  qreal recRoot2 = 1.0/sqrt(2);
+
3155 
+
3156  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
3157  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
3158  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
3159 
+
3160 # ifdef _OPENMP
+
3161 # pragma omp parallel \
+
3162  default (none) \
+
3163  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
3164  recRoot2, sign, numTasks) \
+
3165  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
3166 # endif
+
3167  {
+
3168 # ifdef _OPENMP
+
3169 # pragma omp for schedule (static)
+
3170 # endif
+
3171  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3172  // store current state vector values in temp variables
+
3173  stateRealUp = stateVecRealUp[thisTask];
+
3174  stateImagUp = stateVecImagUp[thisTask];
+
3175 
+
3176  stateRealLo = stateVecRealLo[thisTask];
+
3177  stateImagLo = stateVecImagLo[thisTask];
+
3178 
+
3179  stateVecRealOut[thisTask] = recRoot2*(stateRealUp + sign*stateRealLo);
+
3180  stateVecImagOut[thisTask] = recRoot2*(stateImagUp + sign*stateImagLo);
+
3181  }
+
3182  }
+
3183 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_hadamard().

+

Referenced by statevec_hadamard().

@@ -4046,59 +4047,59 @@

-

Definition at line 3039 of file QuEST_cpu.c.

-
3040 {
-
3041  long long int sizeBlock, sizeHalfBlock;
-
3042  long long int thisBlock, // current block
-
3043  indexUp,indexLo; // current index and corresponding index in lower half block
-
3044 
-
3045  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
3046  long long int thisTask;
-
3047  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
3048 
-
3049  // set dimensions
-
3050  sizeHalfBlock = 1LL << targetQubit;
-
3051  sizeBlock = 2LL * sizeHalfBlock;
-
3052 
-
3053  // Can't use qureg.stateVec as a private OMP var
-
3054  qreal *stateVecReal = qureg.stateVec.real;
-
3055  qreal *stateVecImag = qureg.stateVec.imag;
-
3056 
-
3057  qreal recRoot2 = 1.0/sqrt(2);
-
3058 
-
3059 # ifdef _OPENMP
-
3060 # pragma omp parallel \
-
3061  default (none) \
-
3062  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
-
3063  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
3064 # endif
-
3065  {
-
3066 # ifdef _OPENMP
-
3067 # pragma omp for schedule (static)
-
3068 # endif
-
3069  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3070  thisBlock = thisTask / sizeHalfBlock;
-
3071  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
3072  indexLo = indexUp + sizeHalfBlock;
-
3073 
-
3074  stateRealUp = stateVecReal[indexUp];
-
3075  stateImagUp = stateVecImag[indexUp];
-
3076 
-
3077  stateRealLo = stateVecReal[indexLo];
-
3078  stateImagLo = stateVecImag[indexLo];
-
3079 
-
3080  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
3081  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
3082 
-
3083  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
3084  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
3085  }
-
3086  }
-
3087 }
+

Definition at line 3078 of file QuEST_cpu.c.

+
3079 {
+
3080  long long int sizeBlock, sizeHalfBlock;
+
3081  long long int thisBlock, // current block
+
3082  indexUp,indexLo; // current index and corresponding index in lower half block
+
3083 
+
3084  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
3085  long long int thisTask;
+
3086  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
3087 
+
3088  // set dimensions
+
3089  sizeHalfBlock = 1LL << targetQubit;
+
3090  sizeBlock = 2LL * sizeHalfBlock;
+
3091 
+
3092  // Can't use qureg.stateVec as a private OMP var
+
3093  qreal *stateVecReal = qureg.stateVec.real;
+
3094  qreal *stateVecImag = qureg.stateVec.imag;
+
3095 
+
3096  qreal recRoot2 = 1.0/sqrt(2);
+
3097 
+
3098 # ifdef _OPENMP
+
3099 # pragma omp parallel \
+
3100  default (none) \
+
3101  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, recRoot2, numTasks) \
+
3102  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
3103 # endif
+
3104  {
+
3105 # ifdef _OPENMP
+
3106 # pragma omp for schedule (static)
+
3107 # endif
+
3108  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3109  thisBlock = thisTask / sizeHalfBlock;
+
3110  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
3111  indexLo = indexUp + sizeHalfBlock;
+
3112 
+
3113  stateRealUp = stateVecReal[indexUp];
+
3114  stateImagUp = stateVecImag[indexUp];
+
3115 
+
3116  stateRealLo = stateVecReal[indexLo];
+
3117  stateImagLo = stateVecImag[indexLo];
+
3118 
+
3119  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
+
3120  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
+
3121 
+
3122  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
+
3123  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
+
3124  }
+
3125  }
+
3126 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_hadamard().

+

Referenced by statevec_hadamard().

@@ -4146,59 +4147,59 @@

-

Definition at line 2795 of file QuEST_cpu.c.

-
2799  {
-
2800  long long int numAmps = qureg.numAmpsPerChunk;
-
2801  long long int globalOffset = qureg.chunkId * numAmps;
-
2802 
-
2803  /* stateVecOut is qureg's local state-vector partition, which we modify.
-
2804  * stateVecIn is the pair node's state-vector partition, in an order which
-
2805  * does not necessarily correlate to stateVecOut's
-
2806  */
-
2807  qreal* inReal = stateVecIn.real;
-
2808  qreal* inImag = stateVecIn.imag;
-
2809  qreal* outReal = stateVecOut.real;
-
2810  qreal* outImag = stateVecOut.imag;
-
2811 
-
2812  long long int outInd, outIndGlobal, inInd, inIndGlobal;
-
2813 
-
2814 # ifdef _OPENMP
-
2815 # pragma omp parallel \
-
2816  default (none) \
-
2817  shared (inReal,inImag,outReal,outImag, numAmps,globalOffset, ctrlMask,targMask) \
-
2818  private (outInd,outIndGlobal, inInd,inIndGlobal)
-
2819 # endif
-
2820  {
-
2821 # ifdef _OPENMP
-
2822 # pragma omp for schedule (static)
-
2823 # endif
-
2824  for (outInd = 0; outInd < numAmps; outInd++) {
-
2825 
-
2826  // modify amplitude only if control qubits are 1 for this state
-
2827  outIndGlobal = outInd + globalOffset;
-
2828  if (ctrlMask && ((ctrlMask & outIndGlobal) != ctrlMask))
-
2829  continue;
-
2830  /* it is a premature optimisation to remove this seemingly wasteful abort above,
-
2831  * because the maximum skipped amplitudes is 1/2 that stored in the node
-
2832  * (since this function is not called if all amps should be skipped)
-
2833  */
-
2834 
-
2835  /* unlike statevec_controlledNotDistributed(), we cannot assume stateVecOut
-
2836  * maps contiguously/parallel into stateVecIn; we must map each amplitude, bit-wise.
-
2837  * However, the arithmetic doesn't necessitate knowing the rank of stateVecIn
-
2838  */
-
2839  inIndGlobal = outIndGlobal ^ targMask;
-
2840  inInd = inIndGlobal % numAmps; // = inIndGlobal - pairRank * numAmps
-
2841 
-
2842  outReal[outInd] = inReal[inInd];
-
2843  outImag[outInd] = inImag[inInd];
-
2844  }
-
2845  }
-
2846 }
+

Definition at line 2834 of file QuEST_cpu.c.

+
2838  {
+
2839  long long int numAmps = qureg.numAmpsPerChunk;
+
2840  long long int globalOffset = qureg.chunkId * numAmps;
+
2841 
+
2842  /* stateVecOut is qureg's local state-vector partition, which we modify.
+
2843  * stateVecIn is the pair node's state-vector partition, in an order which
+
2844  * does not necessarily correlate to stateVecOut's
+
2845  */
+
2846  qreal* inReal = stateVecIn.real;
+
2847  qreal* inImag = stateVecIn.imag;
+
2848  qreal* outReal = stateVecOut.real;
+
2849  qreal* outImag = stateVecOut.imag;
+
2850 
+
2851  long long int outInd, outIndGlobal, inInd, inIndGlobal;
+
2852 
+
2853 # ifdef _OPENMP
+
2854 # pragma omp parallel \
+
2855  default (none) \
+
2856  shared (inReal,inImag,outReal,outImag, numAmps,globalOffset, ctrlMask,targMask) \
+
2857  private (outInd,outIndGlobal, inInd,inIndGlobal)
+
2858 # endif
+
2859  {
+
2860 # ifdef _OPENMP
+
2861 # pragma omp for schedule (static)
+
2862 # endif
+
2863  for (outInd = 0; outInd < numAmps; outInd++) {
+
2864 
+
2865  // modify amplitude only if control qubits are 1 for this state
+
2866  outIndGlobal = outInd + globalOffset;
+
2867  if (ctrlMask && ((ctrlMask & outIndGlobal) != ctrlMask))
+
2868  continue;
+
2869  /* it is a premature optimisation to remove this seemingly wasteful abort above,
+
2870  * because the maximum skipped amplitudes is 1/2 that stored in the node
+
2871  * (since this function is not called if all amps should be skipped)
+
2872  */
+
2873 
+
2874  /* unlike statevec_controlledNotDistributed(), we cannot assume stateVecOut
+
2875  * maps contiguously/parallel into stateVecIn; we must map each amplitude, bit-wise.
+
2876  * However, the arithmetic doesn't necessitate knowing the rank of stateVecIn
+
2877  */
+
2878  inIndGlobal = outIndGlobal ^ targMask;
+
2879  inInd = inIndGlobal % numAmps; // = inIndGlobal - pairRank * numAmps
+
2880 
+
2881  outReal[outInd] = inReal[inInd];
+
2882  outImag[outInd] = inImag[inInd];
+
2883  }
+
2884  }
+
2885 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_multiControlledMultiQubitNot().

+

Referenced by statevec_multiControlledMultiQubitNot().

@@ -4234,66 +4235,66 @@

-

Definition at line 2739 of file QuEST_cpu.c.

-
2739  {
-
2740  long long int numAmps = qureg.numAmpsPerChunk;
-
2741  qreal* stateRe = qureg.stateVec.real;
-
2742  qreal* stateIm = qureg.stateVec.imag;
-
2743 
-
2744  long long int globalOffset = qureg.chunkId * numAmps;
-
2745 
-
2746  // each amplitude is swapped with a 'mate' amplitude
-
2747  long long int ampInd, mateInd, globalInd;
-
2748  qreal mateRe, mateIm;
-
2749 
-
2750 # ifdef _OPENMP
-
2751 # pragma omp parallel \
-
2752  default (none) \
-
2753  shared (stateRe,stateIm, numAmps, ctrlMask,targMask, globalOffset) \
-
2754  private (ampInd, mateInd,mateRe,mateIm, globalInd)
-
2755 # endif
-
2756  {
-
2757 # ifdef _OPENMP
-
2758 # pragma omp for schedule (static)
-
2759 # endif
-
2760  for (ampInd = 0; ampInd < numAmps; ampInd++) {
-
2761 
-
2762  /* it may be a premature optimisation to remove the seemingly wasteful continues below,
-
2763  * because the maximum skipped amplitudes is 1/2 that stored in the node
-
2764  * (e.g. since this function is not called if all amps should be skipped via controls),
-
2765  * and since we're memory-bandwidth bottlenecked.
-
2766  */
-
2767 
-
2768  // although amps are local, we may still be running in distributed mode,
-
2769  // and hence need to consult the global index to determine the values of
-
2770  // the control qubits
-
2771  globalInd = ampInd + globalOffset;
-
2772 
-
2773  // modify amplitude only if control qubits are 1 for this state
-
2774  if (ctrlMask && ((ctrlMask & globalInd) != ctrlMask))
-
2775  continue;
-
2776 
-
2777  mateInd = ampInd ^ targMask;
-
2778 
-
2779  // if the mate is behind, it was already processed
-
2780  if (mateInd < ampInd)
-
2781  continue;
-
2782 
-
2783  mateRe = stateRe[mateInd];
-
2784  mateIm = stateIm[mateInd];
-
2785 
-
2786  // swap amp with mate
-
2787  stateRe[mateInd] = stateRe[ampInd];
-
2788  stateIm[mateInd] = stateIm[ampInd];
-
2789  stateRe[ampInd] = mateRe;
-
2790  stateIm[ampInd] = mateIm;
-
2791  }
-
2792  }
-
2793 }
+

Definition at line 2778 of file QuEST_cpu.c.

+
2778  {
+
2779  long long int numAmps = qureg.numAmpsPerChunk;
+
2780  qreal* stateRe = qureg.stateVec.real;
+
2781  qreal* stateIm = qureg.stateVec.imag;
+
2782 
+
2783  long long int globalOffset = qureg.chunkId * numAmps;
+
2784 
+
2785  // each amplitude is swapped with a 'mate' amplitude
+
2786  long long int ampInd, mateInd, globalInd;
+
2787  qreal mateRe, mateIm;
+
2788 
+
2789 # ifdef _OPENMP
+
2790 # pragma omp parallel \
+
2791  default (none) \
+
2792  shared (stateRe,stateIm, numAmps, ctrlMask,targMask, globalOffset) \
+
2793  private (ampInd, mateInd,mateRe,mateIm, globalInd)
+
2794 # endif
+
2795  {
+
2796 # ifdef _OPENMP
+
2797 # pragma omp for schedule (static)
+
2798 # endif
+
2799  for (ampInd = 0; ampInd < numAmps; ampInd++) {
+
2800 
+
2801  /* it may be a premature optimisation to remove the seemingly wasteful continues below,
+
2802  * because the maximum skipped amplitudes is 1/2 that stored in the node
+
2803  * (e.g. since this function is not called if all amps should be skipped via controls),
+
2804  * and since we're memory-bandwidth bottlenecked.
+
2805  */
+
2806 
+
2807  // although amps are local, we may still be running in distributed mode,
+
2808  // and hence need to consult the global index to determine the values of
+
2809  // the control qubits
+
2810  globalInd = ampInd + globalOffset;
+
2811 
+
2812  // modify amplitude only if control qubits are 1 for this state
+
2813  if (ctrlMask && ((ctrlMask & globalInd) != ctrlMask))
+
2814  continue;
+
2815 
+
2816  mateInd = ampInd ^ targMask;
+
2817 
+
2818  // if the mate is behind, it was already processed
+
2819  if (mateInd < ampInd)
+
2820  continue;
+
2821 
+
2822  mateRe = stateRe[mateInd];
+
2823  mateIm = stateIm[mateInd];
+
2824 
+
2825  // swap amp with mate
+
2826  stateRe[mateInd] = stateRe[ampInd];
+
2827  stateIm[mateInd] = stateIm[ampInd];
+
2828  stateRe[ampInd] = mateRe;
+
2829  stateIm[ampInd] = mateIm;
+
2830  }
+
2831  }
+
2832 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_multiControlledMultiQubitNot().

+

Referenced by statevec_multiControlledMultiQubitNot().

@@ -4341,95 +4342,123 @@

-

Definition at line 1901 of file QuEST_cpu.c.

-
1902 {
-
1903  // can't use qureg.stateVec as a private OMP var
-
1904  qreal *reVec = qureg.stateVec.real;
-
1905  qreal *imVec = qureg.stateVec.imag;
-
1906 
-
1907  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
1908  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
-
1909 
-
1910  // the global (between all nodes) index of this node's start index
-
1911  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1912 
-
1913  long long int thisTask;
-
1914  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
-
1915  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
-
1916  long long int ind; // each thread's iteration of amplitudes to modify
-
1917  int i, t, r, c; // each thread's iteration of amps and targets
-
1918  qreal reElem, imElem; // each thread's iteration of u elements
-
1919 
-
1920  // each thread/task will record and modify numTargAmps amplitudes, privately
-
1921  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
-
1922  long long int ampInds[numTargAmps];
-
1923  qreal reAmps[numTargAmps];
-
1924  qreal imAmps[numTargAmps];
-
1925 
-
1926  // we need a sorted targets list to find thisInd00 for each task.
-
1927  // we can't modify targets, because the user-ordering of targets matters in u
-
1928  int sortedTargs[numTargs];
-
1929  for (int t=0; t < numTargs; t++)
-
1930  sortedTargs[t] = targs[t];
-
1931  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
-
1932 
-
1933 # ifdef _OPENMP
-
1934 # pragma omp parallel \
-
1935  default (none) \
-
1936  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
-
1937  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
-
1938 # endif
-
1939  {
-
1940 # ifdef _OPENMP
-
1941 # pragma omp for schedule (static)
-
1942 # endif
-
1943  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1944 
-
1945  // find this task's start index (where all targs are 0)
-
1946  thisInd00 = thisTask;
-
1947  for (t=0; t < numTargs; t++)
-
1948  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
-
1949 
-
1950  // this task only modifies amplitudes if control qubits are 1 for this state
-
1951  thisGlobalInd00 = thisInd00 + globalIndStart;
-
1952  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1953  continue;
-
1954 
-
1955  // determine the indices and record values of this tasks's target amps
-
1956  for (i=0; i < numTargAmps; i++) {
-
1957 
-
1958  // get statevec index of current target qubit assignment
-
1959  ind = thisInd00;
-
1960  for (t=0; t < numTargs; t++)
-
1961  if (extractBit(t, i))
-
1962  ind = flipBit(ind, targs[t]);
-
1963 
-
1964  // update this tasks's private arrays
-
1965  ampInds[i] = ind;
-
1966  reAmps [i] = reVec[ind];
-
1967  imAmps [i] = imVec[ind];
-
1968  }
-
1969 
-
1970  // modify this tasks's target amplitudes
-
1971  for (r=0; r < numTargAmps; r++) {
-
1972  ind = ampInds[r];
-
1973  reVec[ind] = 0;
-
1974  imVec[ind] = 0;
-
1975 
-
1976  for (c=0; c < numTargAmps; c++) {
-
1977  reElem = u.real[r][c];
-
1978  imElem = u.imag[r][c];
-
1979  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
-
1980  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
-
1981  }
-
1982  }
-
1983  }
-
1984  }
-
1985 }
+

Definition at line 1912 of file QuEST_cpu.c.

+
1913 {
+
1914  // can't use qureg.stateVec as a private OMP var
+
1915  qreal *reVec = qureg.stateVec.real;
+
1916  qreal *imVec = qureg.stateVec.imag;
+
1917 
+
1918  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
+
1919  long long int numTargAmps = 1 << u.numQubits; // num amps to be modified by each task
+
1920 
+
1921  // the global (between all nodes) index of this node's start index
+
1922  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
+
1923 
+
1924  long long int thisTask;
+
1925  long long int thisInd00; // this thread's index of |..0..0..> (target qubits = 0)
+
1926  long long int thisGlobalInd00; // the global (between all nodes) index of this thread's |..0..0..> state
+
1927  long long int ind; // each thread's iteration of amplitudes to modify
+
1928  int i, t, r, c; // each thread's iteration of amps and targets
+
1929  qreal reElem, imElem; // each thread's iteration of u elements
+
1930 
+
1931  // each thread/task will record and modify numTargAmps amplitudes, privately
+
1932  // (of course, tasks eliminated by the ctrlMask won't edit their allocation)
+
1933  //
+
1934  // If we're NOT on windows, we can fortunately use the stack directly
+
1935  #ifndef _WIN32
+
1936  long long int ampInds[numTargAmps];
+
1937  qreal reAmps[numTargAmps];
+
1938  qreal imAmps[numTargAmps];
+
1939 
+
1940  int sortedTargs[numTargs];
+
1941  // on Windows, with no VLA, we can use _malloca to allocate on stack (must free)
+
1942  #else
+
1943  long long int* ampInds;
+
1944  qreal* reAmps;
+
1945  qreal* imAmps;
+
1946  int* sortedTargs = (int*) _malloca(numTargs * sizeof *sortedTargs);
+
1947  #endif
+
1948 
+
1949  // we need a sorted targets list to find thisInd00 for each task.
+
1950  // we can't modify targets, because the user-ordering of targets matters in u
+
1951  for (int t=0; t < numTargs; t++)
+
1952  sortedTargs[t] = targs[t];
+
1953  qsort(sortedTargs, numTargs, sizeof(int), qsortComp);
+
1954 
+
1955 # ifdef _OPENMP
+
1956 # pragma omp parallel \
+
1957  default (none) \
+
1958  shared (reVec,imVec, numTasks,numTargAmps,globalIndStart, ctrlMask,targs,sortedTargs,u,numTargs) \
+
1959  private (thisTask,thisInd00,thisGlobalInd00,ind,i,t,r,c,reElem,imElem, ampInds,reAmps,imAmps)
+
1960 # endif
+
1961  {
+
1962  // when manually allocating array memory (on Windows), this must be done in each thread
+
1963  // separately and is not performed automatically by declaring a var as omp-private
+
1964  # ifdef _WIN32
+
1965  ampInds = (long long int*) _malloca(numTargAmps * sizeof *ampInds);
+
1966  reAmps = (qreal*) _malloca(numTargAmps * sizeof *reAmps);
+
1967  imAmps = (qreal*) _malloca(numTargAmps * sizeof *imAmps);
+
1968  # endif
+
1969 # ifdef _OPENMP
+
1970 # pragma omp for schedule (static)
+
1971 # endif
+
1972  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
1973 
+
1974  // find this task's start index (where all targs are 0)
+
1975  thisInd00 = thisTask;
+
1976  for (t=0; t < numTargs; t++)
+
1977  thisInd00 = insertZeroBit(thisInd00, sortedTargs[t]);
+
1978 
+
1979  // this task only modifies amplitudes if control qubits are 1 for this state
+
1980  thisGlobalInd00 = thisInd00 + globalIndStart;
+
1981  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
+
1982  continue;
+
1983 
+
1984  // determine the indices and record values of this tasks's target amps
+
1985  for (i=0; i < numTargAmps; i++) {
+
1986 
+
1987  // get statevec index of current target qubit assignment
+
1988  ind = thisInd00;
+
1989  for (t=0; t < numTargs; t++)
+
1990  if (extractBit(t, i))
+
1991  ind = flipBit(ind, targs[t]);
+
1992 
+
1993  // update this tasks's private arrays
+
1994  ampInds[i] = ind;
+
1995  reAmps [i] = reVec[ind];
+
1996  imAmps [i] = imVec[ind];
+
1997  }
+
1998 
+
1999  // modify this tasks's target amplitudes
+
2000  for (r=0; r < numTargAmps; r++) {
+
2001  ind = ampInds[r];
+
2002  reVec[ind] = 0;
+
2003  imVec[ind] = 0;
+
2004 
+
2005  for (c=0; c < numTargAmps; c++) {
+
2006  reElem = u.real[r][c];
+
2007  imElem = u.imag[r][c];
+
2008  reVec[ind] += reAmps[c]*reElem - imAmps[c]*imElem;
+
2009  imVec[ind] += reAmps[c]*imElem + imAmps[c]*reElem;
+
2010  }
+
2011  }
+
2012  }
+
2013  // on Windows, we must explicitly free the stack structures
+
2014  #ifdef _WIN32
+
2015  _freea(ampInds);
+
2016  _freea(reAmps);
+
2017  _freea(imAmps);
+
2018  #endif
+
2019  }
+
2020 
+
2021  #ifdef _WIN32
+
2022  _freea(sortedTargs);
+
2023  #endif
+
2024 }
-

References Qureg::chunkId, extractBit(), flipBit(), ComplexMatrixN::imag, insertZeroBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, qsortComp(), ComplexMatrixN::real, and Qureg::stateVec.

+

References Qureg::chunkId, extractBit(), flipBit(), ComplexMatrixN::imag, insertZeroBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, qsortComp(), ComplexMatrixN::real, and Qureg::stateVec.

-

Referenced by statevec_multiControlledMultiQubitUnitary().

+

Referenced by statevec_multiControlledMultiQubitUnitary().

@@ -4477,105 +4506,105 @@

-

Definition at line 1802 of file QuEST_cpu.c.

-
1802  {
-
1803 
-
1804  // can't use qureg.stateVec as a private OMP var
-
1805  qreal *reVec = qureg.stateVec.real;
-
1806  qreal *imVec = qureg.stateVec.imag;
-
1807 
-
1808  // the global (between all nodes) index of this node's start index
-
1809  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
-
1810 
-
1811  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
-
1812  long long int thisTask;
-
1813  long long int thisGlobalInd00;
-
1814  long long int ind00, ind01, ind10, ind11;
-
1815  qreal re00, re01, re10, re11;
-
1816  qreal im00, im01, im10, im11;
-
1817 
-
1818 # ifdef _OPENMP
-
1819 # pragma omp parallel \
-
1820  default (none) \
-
1821  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
-
1822  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
-
1823 # endif
-
1824  {
-
1825 # ifdef _OPENMP
-
1826 # pragma omp for schedule (static)
-
1827 # endif
-
1828  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
1829 
-
1830  // determine ind00 of |..0..0..>
-
1831  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1832 
-
1833  // skip amplitude if controls aren't in 1 state (overloaded for speed)
-
1834  thisGlobalInd00 = ind00 + globalIndStart;
-
1835  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
-
1836  continue;
-
1837 
-
1838  // inds of |..0..1..>, |..1..0..> and |..1..1..>
-
1839  ind01 = flipBit(ind00, q1);
-
1840  ind10 = flipBit(ind00, q2);
-
1841  ind11 = flipBit(ind01, q2);
-
1842 
-
1843  // extract statevec amplitudes
-
1844  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1845  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1846  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1847  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1848 
-
1849  // apply u * {amp00, amp01, amp10, amp11}
-
1850  reVec[ind00] =
-
1851  u.real[0][0]*re00 - u.imag[0][0]*im00 +
-
1852  u.real[0][1]*re01 - u.imag[0][1]*im01 +
-
1853  u.real[0][2]*re10 - u.imag[0][2]*im10 +
-
1854  u.real[0][3]*re11 - u.imag[0][3]*im11;
-
1855  imVec[ind00] =
-
1856  u.imag[0][0]*re00 + u.real[0][0]*im00 +
-
1857  u.imag[0][1]*re01 + u.real[0][1]*im01 +
-
1858  u.imag[0][2]*re10 + u.real[0][2]*im10 +
-
1859  u.imag[0][3]*re11 + u.real[0][3]*im11;
-
1860 
-
1861  reVec[ind01] =
-
1862  u.real[1][0]*re00 - u.imag[1][0]*im00 +
-
1863  u.real[1][1]*re01 - u.imag[1][1]*im01 +
-
1864  u.real[1][2]*re10 - u.imag[1][2]*im10 +
-
1865  u.real[1][3]*re11 - u.imag[1][3]*im11;
-
1866  imVec[ind01] =
-
1867  u.imag[1][0]*re00 + u.real[1][0]*im00 +
-
1868  u.imag[1][1]*re01 + u.real[1][1]*im01 +
-
1869  u.imag[1][2]*re10 + u.real[1][2]*im10 +
-
1870  u.imag[1][3]*re11 + u.real[1][3]*im11;
+

Definition at line 1813 of file QuEST_cpu.c.

+
1813  {
+
1814 
+
1815  // can't use qureg.stateVec as a private OMP var
+
1816  qreal *reVec = qureg.stateVec.real;
+
1817  qreal *imVec = qureg.stateVec.imag;
+
1818 
+
1819  // the global (between all nodes) index of this node's start index
+
1820  long long int globalIndStart = qureg.chunkId*qureg.numAmpsPerChunk;
+
1821 
+
1822  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 4 amplitudes
+
1823  long long int thisTask;
+
1824  long long int thisGlobalInd00;
+
1825  long long int ind00, ind01, ind10, ind11;
+
1826  qreal re00, re01, re10, re11;
+
1827  qreal im00, im01, im10, im11;
+
1828 
+
1829 # ifdef _OPENMP
+
1830 # pragma omp parallel \
+
1831  default (none) \
+
1832  shared (reVec,imVec,globalIndStart,numTasks,ctrlMask,u,q2,q1) \
+
1833  private (thisTask, thisGlobalInd00, ind00,ind01,ind10,ind11, re00,re01,re10,re11, im00,im01,im10,im11)
+
1834 # endif
+
1835  {
+
1836 # ifdef _OPENMP
+
1837 # pragma omp for schedule (static)
+
1838 # endif
+
1839  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
1840 
+
1841  // determine ind00 of |..0..0..>
+
1842  ind00 = insertTwoZeroBits(thisTask, q1, q2);
+
1843 
+
1844  // skip amplitude if controls aren't in 1 state (overloaded for speed)
+
1845  thisGlobalInd00 = ind00 + globalIndStart;
+
1846  if (ctrlMask && ((ctrlMask & thisGlobalInd00) != ctrlMask))
+
1847  continue;
+
1848 
+
1849  // inds of |..0..1..>, |..1..0..> and |..1..1..>
+
1850  ind01 = flipBit(ind00, q1);
+
1851  ind10 = flipBit(ind00, q2);
+
1852  ind11 = flipBit(ind01, q2);
+
1853 
+
1854  // extract statevec amplitudes
+
1855  re00 = reVec[ind00]; im00 = imVec[ind00];
+
1856  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1857  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1858  re11 = reVec[ind11]; im11 = imVec[ind11];
+
1859 
+
1860  // apply u * {amp00, amp01, amp10, amp11}
+
1861  reVec[ind00] =
+
1862  u.real[0][0]*re00 - u.imag[0][0]*im00 +
+
1863  u.real[0][1]*re01 - u.imag[0][1]*im01 +
+
1864  u.real[0][2]*re10 - u.imag[0][2]*im10 +
+
1865  u.real[0][3]*re11 - u.imag[0][3]*im11;
+
1866  imVec[ind00] =
+
1867  u.imag[0][0]*re00 + u.real[0][0]*im00 +
+
1868  u.imag[0][1]*re01 + u.real[0][1]*im01 +
+
1869  u.imag[0][2]*re10 + u.real[0][2]*im10 +
+
1870  u.imag[0][3]*re11 + u.real[0][3]*im11;
1871 
-
1872  reVec[ind10] =
-
1873  u.real[2][0]*re00 - u.imag[2][0]*im00 +
-
1874  u.real[2][1]*re01 - u.imag[2][1]*im01 +
-
1875  u.real[2][2]*re10 - u.imag[2][2]*im10 +
-
1876  u.real[2][3]*re11 - u.imag[2][3]*im11;
-
1877  imVec[ind10] =
-
1878  u.imag[2][0]*re00 + u.real[2][0]*im00 +
-
1879  u.imag[2][1]*re01 + u.real[2][1]*im01 +
-
1880  u.imag[2][2]*re10 + u.real[2][2]*im10 +
-
1881  u.imag[2][3]*re11 + u.real[2][3]*im11;
+
1872  reVec[ind01] =
+
1873  u.real[1][0]*re00 - u.imag[1][0]*im00 +
+
1874  u.real[1][1]*re01 - u.imag[1][1]*im01 +
+
1875  u.real[1][2]*re10 - u.imag[1][2]*im10 +
+
1876  u.real[1][3]*re11 - u.imag[1][3]*im11;
+
1877  imVec[ind01] =
+
1878  u.imag[1][0]*re00 + u.real[1][0]*im00 +
+
1879  u.imag[1][1]*re01 + u.real[1][1]*im01 +
+
1880  u.imag[1][2]*re10 + u.real[1][2]*im10 +
+
1881  u.imag[1][3]*re11 + u.real[1][3]*im11;
1882 
-
1883  reVec[ind11] =
-
1884  u.real[3][0]*re00 - u.imag[3][0]*im00 +
-
1885  u.real[3][1]*re01 - u.imag[3][1]*im01 +
-
1886  u.real[3][2]*re10 - u.imag[3][2]*im10 +
-
1887  u.real[3][3]*re11 - u.imag[3][3]*im11;
-
1888  imVec[ind11] =
-
1889  u.imag[3][0]*re00 + u.real[3][0]*im00 +
-
1890  u.imag[3][1]*re01 + u.real[3][1]*im01 +
-
1891  u.imag[3][2]*re10 + u.real[3][2]*im10 +
-
1892  u.imag[3][3]*re11 + u.real[3][3]*im11;
-
1893  }
-
1894  }
-
1895 }
+
1883  reVec[ind10] =
+
1884  u.real[2][0]*re00 - u.imag[2][0]*im00 +
+
1885  u.real[2][1]*re01 - u.imag[2][1]*im01 +
+
1886  u.real[2][2]*re10 - u.imag[2][2]*im10 +
+
1887  u.real[2][3]*re11 - u.imag[2][3]*im11;
+
1888  imVec[ind10] =
+
1889  u.imag[2][0]*re00 + u.real[2][0]*im00 +
+
1890  u.imag[2][1]*re01 + u.real[2][1]*im01 +
+
1891  u.imag[2][2]*re10 + u.real[2][2]*im10 +
+
1892  u.imag[2][3]*re11 + u.real[2][3]*im11;
+
1893 
+
1894  reVec[ind11] =
+
1895  u.real[3][0]*re00 - u.imag[3][0]*im00 +
+
1896  u.real[3][1]*re01 - u.imag[3][1]*im01 +
+
1897  u.real[3][2]*re10 - u.imag[3][2]*im10 +
+
1898  u.real[3][3]*re11 - u.imag[3][3]*im11;
+
1899  imVec[ind11] =
+
1900  u.imag[3][0]*re00 + u.real[3][0]*im00 +
+
1901  u.imag[3][1]*re01 + u.real[3][1]*im01 +
+
1902  u.imag[3][2]*re10 + u.real[3][2]*im10 +
+
1903  u.imag[3][3]*re11 + u.real[3][3]*im11;
+
1904  }
+
1905  }
+
1906 }

References Qureg::chunkId, flipBit(), ComplexMatrix4::imag, insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, ComplexMatrix4::real, and Qureg::stateVec.

-

Referenced by statevec_multiControlledTwoQubitUnitary().

+

Referenced by statevec_multiControlledTwoQubitUnitary().

@@ -4664,53 +4693,53 @@

Definition at line 2503 of file QuEST_cpu.c.

-
2511 {
-
2512 
-
2513  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2514  long long int thisTask;
-
2515  long long int numTasks=qureg.numAmpsPerChunk;
-
2516  long long int chunkSize=qureg.numAmpsPerChunk;
-
2517  long long int chunkId=qureg.chunkId;
-
2518 
-
2519  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2520  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2521  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2522  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2523  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2524 
-
2525 # ifdef _OPENMP
-
2526 # pragma omp parallel \
-
2527  default (none) \
-
2528  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2529  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
-
2530  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2531 # endif
-
2532  {
-
2533 # ifdef _OPENMP
-
2534 # pragma omp for schedule (static)
-
2535 # endif
-
2536  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2537  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2538  // store current state vector values in temp variables
-
2539  stateRealUp = stateVecRealUp[thisTask];
-
2540  stateImagUp = stateVecImagUp[thisTask];
-
2541 
-
2542  stateRealLo = stateVecRealLo[thisTask];
-
2543  stateImagLo = stateVecImagLo[thisTask];
-
2544 
-
2545  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2546  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2547  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2548  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2549  }
-
2550  }
-
2551  }
-
2552 }
+

Definition at line 2542 of file QuEST_cpu.c.

+
2550 {
+
2551 
+
2552  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2553  long long int thisTask;
+
2554  long long int numTasks=qureg.numAmpsPerChunk;
+
2555  long long int chunkSize=qureg.numAmpsPerChunk;
+
2556  long long int chunkId=qureg.chunkId;
+
2557 
+
2558  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2559  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2560  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2561  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2562  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2563 
+
2564 # ifdef _OPENMP
+
2565 # pragma omp parallel \
+
2566  default (none) \
+
2567  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2568  rot1Real,rot1Imag, rot2Real,rot2Imag, ctrlQubitsMask,ctrlFlipMask, numTasks,chunkId,chunkSize) \
+
2569  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2570 # endif
+
2571  {
+
2572 # ifdef _OPENMP
+
2573 # pragma omp for schedule (static)
+
2574 # endif
+
2575  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2576  if (ctrlQubitsMask == (ctrlQubitsMask & ((thisTask+chunkId*chunkSize) ^ ctrlFlipMask))) {
+
2577  // store current state vector values in temp variables
+
2578  stateRealUp = stateVecRealUp[thisTask];
+
2579  stateImagUp = stateVecImagUp[thisTask];
+
2580 
+
2581  stateRealLo = stateVecRealLo[thisTask];
+
2582  stateImagLo = stateVecImagLo[thisTask];
+
2583 
+
2584  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2585  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2586  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2587  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2588  }
+
2589  }
+
2590  }
+
2591 }

References Qureg::chunkId, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_multiControlledUnitary().

+

Referenced by statevec_multiControlledUnitary().

@@ -4758,74 +4787,74 @@

-

Definition at line 2229 of file QuEST_cpu.c.

-
2233 {
-
2234  long long int sizeBlock, sizeHalfBlock;
-
2235  long long int thisBlock, // current block
-
2236  indexUp,indexLo; // current index and corresponding index in lower half block
-
2237 
-
2238  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2239  long long int thisTask;
-
2240  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2241  long long int chunkSize=qureg.numAmpsPerChunk;
-
2242  long long int chunkId=qureg.chunkId;
-
2243 
-
2244  // set dimensions
-
2245  sizeHalfBlock = 1LL << targetQubit;
-
2246  sizeBlock = 2LL * sizeHalfBlock;
-
2247 
-
2248  // Can't use qureg.stateVec as a private OMP var
-
2249  qreal *stateVecReal = qureg.stateVec.real;
-
2250  qreal *stateVecImag = qureg.stateVec.imag;
-
2251 
-
2252 # ifdef _OPENMP
-
2253 # pragma omp parallel \
-
2254  default (none) \
-
2255  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
-
2256  numTasks,chunkId,chunkSize) \
-
2257  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2258 # endif
-
2259  {
-
2260 # ifdef _OPENMP
-
2261 # pragma omp for schedule (static)
-
2262 # endif
-
2263  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2264 
-
2265  thisBlock = thisTask / sizeHalfBlock;
-
2266  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2267  indexLo = indexUp + sizeHalfBlock;
-
2268 
-
2269 
-
2270  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
-
2271  // if this equals the control mask, the control qubits have the desired values in the basis index
-
2272  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
-
2273  // store current state vector values in temp variables
-
2274  stateRealUp = stateVecReal[indexUp];
-
2275  stateImagUp = stateVecImag[indexUp];
+

Definition at line 2268 of file QuEST_cpu.c.

+
2272 {
+
2273  long long int sizeBlock, sizeHalfBlock;
+
2274  long long int thisBlock, // current block
+
2275  indexUp,indexLo; // current index and corresponding index in lower half block
2276 
-
2277  stateRealLo = stateVecReal[indexLo];
-
2278  stateImagLo = stateVecImag[indexLo];
-
2279 
-
2280  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2281  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2282  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2283  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2284  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2285 
-
2286  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2287  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2288  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2289  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2290  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2291  }
-
2292  }
-
2293  }
-
2294 
-
2295 }
+
2277  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2278  long long int thisTask;
+
2279  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2280  long long int chunkSize=qureg.numAmpsPerChunk;
+
2281  long long int chunkId=qureg.chunkId;
+
2282 
+
2283  // set dimensions
+
2284  sizeHalfBlock = 1LL << targetQubit;
+
2285  sizeBlock = 2LL * sizeHalfBlock;
+
2286 
+
2287  // Can't use qureg.stateVec as a private OMP var
+
2288  qreal *stateVecReal = qureg.stateVec.real;
+
2289  qreal *stateVecImag = qureg.stateVec.imag;
+
2290 
+
2291 # ifdef _OPENMP
+
2292 # pragma omp parallel \
+
2293  default (none) \
+
2294  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u, ctrlQubitsMask,ctrlFlipMask, \
+
2295  numTasks,chunkId,chunkSize) \
+
2296  private (thisTask,thisBlock, indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2297 # endif
+
2298  {
+
2299 # ifdef _OPENMP
+
2300 # pragma omp for schedule (static)
+
2301 # endif
+
2302  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2303 
+
2304  thisBlock = thisTask / sizeHalfBlock;
+
2305  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2306  indexLo = indexUp + sizeHalfBlock;
+
2307 
+
2308 
+
2309  // take the basis index, flip the designated (XOR) 'control' bits, AND with the controls.
+
2310  // if this equals the control mask, the control qubits have the desired values in the basis index
+
2311  if (ctrlQubitsMask == (ctrlQubitsMask & ((indexUp+chunkId*chunkSize) ^ ctrlFlipMask))) {
+
2312  // store current state vector values in temp variables
+
2313  stateRealUp = stateVecReal[indexUp];
+
2314  stateImagUp = stateVecImag[indexUp];
+
2315 
+
2316  stateRealLo = stateVecReal[indexLo];
+
2317  stateImagLo = stateVecImag[indexLo];
+
2318 
+
2319  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2320  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2321  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2322  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2323  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2324 
+
2325  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2326  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2327  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2328  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2329  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2330  }
+
2331  }
+
2332  }
+
2333 
+
2334 }

References Qureg::chunkId, ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

-

Referenced by statevec_multiControlledUnitary().

+

Referenced by statevec_multiControlledUnitary().

@@ -4875,35 +4904,35 @@

Definition at line 2612 of file QuEST_cpu.c.

-
2615 {
-
2616 
-
2617  long long int thisTask;
-
2618  long long int numTasks=qureg.numAmpsPerChunk;
-
2619 
-
2620  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2621  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2622 
-
2623 # ifdef _OPENMP
-
2624 # pragma omp parallel \
-
2625  default (none) \
-
2626  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
-
2627  private (thisTask)
-
2628 # endif
-
2629  {
-
2630 # ifdef _OPENMP
-
2631 # pragma omp for schedule (static)
-
2632 # endif
-
2633  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2634  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
-
2635  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
-
2636  }
-
2637  }
-
2638 }
+

Definition at line 2651 of file QuEST_cpu.c.

+
2654 {
+
2655 
+
2656  long long int thisTask;
+
2657  long long int numTasks=qureg.numAmpsPerChunk;
+
2658 
+
2659  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2660  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2661 
+
2662 # ifdef _OPENMP
+
2663 # pragma omp parallel \
+
2664  default (none) \
+
2665  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut,numTasks) \
+
2666  private (thisTask)
+
2667 # endif
+
2668  {
+
2669 # ifdef _OPENMP
+
2670 # pragma omp for schedule (static)
+
2671 # endif
+
2672  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2673  stateVecRealOut[thisTask] = stateVecRealIn[thisTask];
+
2674  stateVecImagOut[thisTask] = stateVecImagIn[thisTask];
+
2675  }
+
2676  }
+
2677 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_pauliX().

+

Referenced by statevec_pauliX().

@@ -4933,55 +4962,55 @@

-

Definition at line 2554 of file QuEST_cpu.c.

-
2555 {
-
2556  long long int sizeBlock, sizeHalfBlock;
-
2557  long long int thisBlock, // current block
-
2558  indexUp,indexLo; // current index and corresponding index in lower half block
-
2559 
-
2560  qreal stateRealUp,stateImagUp;
-
2561  long long int thisTask;
-
2562  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2563 
-
2564  // set dimensions
-
2565  sizeHalfBlock = 1LL << targetQubit;
-
2566  sizeBlock = 2LL * sizeHalfBlock;
-
2567 
-
2568  // Can't use qureg.stateVec as a private OMP var
-
2569  qreal *stateVecReal = qureg.stateVec.real;
-
2570  qreal *stateVecImag = qureg.stateVec.imag;
-
2571 
-
2572 # ifdef _OPENMP
-
2573 # pragma omp parallel \
-
2574  default (none) \
-
2575  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
-
2576  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2577 # endif
-
2578  {
-
2579 # ifdef _OPENMP
-
2580 # pragma omp for schedule (static)
-
2581 # endif
-
2582  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2583  thisBlock = thisTask / sizeHalfBlock;
-
2584  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2585  indexLo = indexUp + sizeHalfBlock;
-
2586 
-
2587  stateRealUp = stateVecReal[indexUp];
-
2588  stateImagUp = stateVecImag[indexUp];
-
2589 
-
2590  stateVecReal[indexUp] = stateVecReal[indexLo];
-
2591  stateVecImag[indexUp] = stateVecImag[indexLo];
-
2592 
-
2593  stateVecReal[indexLo] = stateRealUp;
-
2594  stateVecImag[indexLo] = stateImagUp;
-
2595  }
-
2596  }
-
2597 
-
2598 }
+

Definition at line 2593 of file QuEST_cpu.c.

+
2594 {
+
2595  long long int sizeBlock, sizeHalfBlock;
+
2596  long long int thisBlock, // current block
+
2597  indexUp,indexLo; // current index and corresponding index in lower half block
+
2598 
+
2599  qreal stateRealUp,stateImagUp;
+
2600  long long int thisTask;
+
2601  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2602 
+
2603  // set dimensions
+
2604  sizeHalfBlock = 1LL << targetQubit;
+
2605  sizeBlock = 2LL * sizeHalfBlock;
+
2606 
+
2607  // Can't use qureg.stateVec as a private OMP var
+
2608  qreal *stateVecReal = qureg.stateVec.real;
+
2609  qreal *stateVecImag = qureg.stateVec.imag;
+
2610 
+
2611 # ifdef _OPENMP
+
2612 # pragma omp parallel \
+
2613  default (none) \
+
2614  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks) \
+
2615  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
+
2616 # endif
+
2617  {
+
2618 # ifdef _OPENMP
+
2619 # pragma omp for schedule (static)
+
2620 # endif
+
2621  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2622  thisBlock = thisTask / sizeHalfBlock;
+
2623  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2624  indexLo = indexUp + sizeHalfBlock;
+
2625 
+
2626  stateRealUp = stateVecReal[indexUp];
+
2627  stateImagUp = stateVecImag[indexUp];
+
2628 
+
2629  stateVecReal[indexUp] = stateVecReal[indexLo];
+
2630  stateVecImag[indexUp] = stateVecImag[indexLo];
+
2631 
+
2632  stateVecReal[indexLo] = stateRealUp;
+
2633  stateVecImag[indexLo] = stateImagUp;
+
2634  }
+
2635  }
+
2636 
+
2637 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_pauliX().

+

Referenced by statevec_pauliX().

@@ -5045,40 +5074,40 @@

Definition at line 2906 of file QuEST_cpu.c.

-
2910 {
-
2911 
-
2912  long long int thisTask;
-
2913  long long int numTasks=qureg.numAmpsPerChunk;
-
2914 
-
2915  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
-
2916  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2917 
-
2918  int realSign=1, imagSign=1;
-
2919  if (updateUpper) imagSign=-1;
-
2920  else realSign = -1;
-
2921 
-
2922 # ifdef _OPENMP
-
2923 # pragma omp parallel \
-
2924  default (none) \
-
2925  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
-
2926  realSign,imagSign, numTasks,conjFac) \
-
2927  private (thisTask)
-
2928 # endif
-
2929  {
-
2930 # ifdef _OPENMP
-
2931 # pragma omp for schedule (static)
-
2932 # endif
-
2933  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2934  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
-
2935  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
-
2936  }
-
2937  }
-
2938 }
+

Definition at line 2945 of file QuEST_cpu.c.

+
2949 {
+
2950 
+
2951  long long int thisTask;
+
2952  long long int numTasks=qureg.numAmpsPerChunk;
+
2953 
+
2954  qreal *stateVecRealIn=stateVecIn.real, *stateVecImagIn=stateVecIn.imag;
+
2955  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2956 
+
2957  int realSign=1, imagSign=1;
+
2958  if (updateUpper) imagSign=-1;
+
2959  else realSign = -1;
+
2960 
+
2961 # ifdef _OPENMP
+
2962 # pragma omp parallel \
+
2963  default (none) \
+
2964  shared (stateVecRealIn,stateVecImagIn,stateVecRealOut,stateVecImagOut, \
+
2965  realSign,imagSign, numTasks,conjFac) \
+
2966  private (thisTask)
+
2967 # endif
+
2968  {
+
2969 # ifdef _OPENMP
+
2970 # pragma omp for schedule (static)
+
2971 # endif
+
2972  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2973  stateVecRealOut[thisTask] = conjFac * realSign * stateVecImagIn[thisTask];
+
2974  stateVecImagOut[thisTask] = conjFac * imagSign * stateVecRealIn[thisTask];
+
2975  }
+
2976  }
+
2977 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by statevec_pauliY(), and statevec_pauliYConj().

+

Referenced by statevec_pauliY(), and statevec_pauliYConj().

@@ -5114,53 +5143,53 @@

-

Definition at line 2848 of file QuEST_cpu.c.

-
2849 {
-
2850  long long int sizeBlock, sizeHalfBlock;
-
2851  long long int thisBlock, // current block
-
2852  indexUp,indexLo; // current index and corresponding index in lower half block
-
2853 
-
2854  qreal stateRealUp,stateImagUp;
-
2855  long long int thisTask;
-
2856  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2857 
-
2858  // set dimensions
-
2859  sizeHalfBlock = 1LL << targetQubit;
-
2860  sizeBlock = 2LL * sizeHalfBlock;
-
2861 
-
2862  // Can't use qureg.stateVec as a private OMP var
-
2863  qreal *stateVecReal = qureg.stateVec.real;
-
2864  qreal *stateVecImag = qureg.stateVec.imag;
-
2865 
-
2866 # ifdef _OPENMP
-
2867 # pragma omp parallel \
-
2868  default (none) \
-
2869  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
-
2870  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
-
2871 # endif
-
2872  {
-
2873 # ifdef _OPENMP
-
2874 # pragma omp for schedule (static)
-
2875 # endif
-
2876  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2877  thisBlock = thisTask / sizeHalfBlock;
-
2878  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2879  indexLo = indexUp + sizeHalfBlock;
-
2880 
-
2881  stateRealUp = stateVecReal[indexUp];
-
2882  stateImagUp = stateVecImag[indexUp];
-
2883 
-
2884  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
2885  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
2886  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
2887  stateVecImag[indexLo] = conjFac * stateRealUp;
-
2888  }
-
2889  }
-
2890 }
+

Definition at line 2887 of file QuEST_cpu.c.

+
2888 {
+
2889  long long int sizeBlock, sizeHalfBlock;
+
2890  long long int thisBlock, // current block
+
2891  indexUp,indexLo; // current index and corresponding index in lower half block
+
2892 
+
2893  qreal stateRealUp,stateImagUp;
+
2894  long long int thisTask;
+
2895  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2896 
+
2897  // set dimensions
+
2898  sizeHalfBlock = 1LL << targetQubit;
+
2899  sizeBlock = 2LL * sizeHalfBlock;
+
2900 
+
2901  // Can't use qureg.stateVec as a private OMP var
+
2902  qreal *stateVecReal = qureg.stateVec.real;
+
2903  qreal *stateVecImag = qureg.stateVec.imag;
+
2904 
+
2905 # ifdef _OPENMP
+
2906 # pragma omp parallel \
+
2907  default (none) \
+
2908  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, numTasks,conjFac) \
+
2909  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp)
+
2910 # endif
+
2911  {
+
2912 # ifdef _OPENMP
+
2913 # pragma omp for schedule (static)
+
2914 # endif
+
2915  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2916  thisBlock = thisTask / sizeHalfBlock;
+
2917  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2918  indexLo = indexUp + sizeHalfBlock;
+
2919 
+
2920  stateRealUp = stateVecReal[indexUp];
+
2921  stateImagUp = stateVecImag[indexUp];
+
2922 
+
2923  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
2924  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
2925  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
2926  stateVecImag[indexLo] = conjFac * stateRealUp;
+
2927  }
+
2928  }
+
2929 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_pauliY(), and statevec_pauliYConj().

+

Referenced by statevec_pauliY(), and statevec_pauliYConj().

@@ -5204,50 +5233,50 @@

Definition at line 3925 of file QuEST_cpu.c.

-
3925  {
-
3926 
-
3927  // can't use qureg.stateVec as a private OMP var
-
3928  qreal *reVec = qureg.stateVec.real;
-
3929  qreal *imVec = qureg.stateVec.imag;
-
3930  qreal *rePairVec = qureg.pairStateVec.real;
-
3931  qreal *imPairVec = qureg.pairStateVec.imag;
-
3932 
-
3933  long long int numLocalAmps = qureg.numAmpsPerChunk;
-
3934  long long int globalStartInd = qureg.chunkId * numLocalAmps;
-
3935  long long int pairGlobalStartInd = pairRank * numLocalAmps;
-
3936 
-
3937  long long int localInd, globalInd;
-
3938  long long int pairLocalInd, pairGlobalInd;
-
3939 
-
3940 # ifdef _OPENMP
-
3941 # pragma omp parallel \
-
3942  default (none) \
-
3943  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
-
3944  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
-
3945 # endif
-
3946  {
-
3947 # ifdef _OPENMP
-
3948 # pragma omp for schedule (static)
-
3949 # endif
-
3950  for (localInd=0; localInd < numLocalAmps; localInd++) {
-
3951 
-
3952  globalInd = globalStartInd + localInd;
-
3953  if (isOddParity(globalInd, qb1, qb2)) {
-
3954 
-
3955  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
-
3956  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
-
3957 
-
3958  reVec[localInd] = rePairVec[pairLocalInd];
-
3959  imVec[localInd] = imPairVec[pairLocalInd];
-
3960  }
-
3961  }
-
3962  }
-
3963 }
+

Definition at line 3965 of file QuEST_cpu.c.

+
3965  {
+
3966 
+
3967  // can't use qureg.stateVec as a private OMP var
+
3968  qreal *reVec = qureg.stateVec.real;
+
3969  qreal *imVec = qureg.stateVec.imag;
+
3970  qreal *rePairVec = qureg.pairStateVec.real;
+
3971  qreal *imPairVec = qureg.pairStateVec.imag;
+
3972 
+
3973  long long int numLocalAmps = qureg.numAmpsPerChunk;
+
3974  long long int globalStartInd = qureg.chunkId * numLocalAmps;
+
3975  long long int pairGlobalStartInd = pairRank * numLocalAmps;
+
3976 
+
3977  long long int localInd, globalInd;
+
3978  long long int pairLocalInd, pairGlobalInd;
+
3979 
+
3980 # ifdef _OPENMP
+
3981 # pragma omp parallel \
+
3982  default (none) \
+
3983  shared (reVec,imVec,rePairVec,imPairVec,numLocalAmps,globalStartInd,pairGlobalStartInd,qb1,qb2) \
+
3984  private (localInd,globalInd, pairLocalInd,pairGlobalInd)
+
3985 # endif
+
3986  {
+
3987 # ifdef _OPENMP
+
3988 # pragma omp for schedule (static)
+
3989 # endif
+
3990  for (localInd=0; localInd < numLocalAmps; localInd++) {
+
3991 
+
3992  globalInd = globalStartInd + localInd;
+
3993  if (isOddParity(globalInd, qb1, qb2)) {
+
3994 
+
3995  pairGlobalInd = flipBit(flipBit(globalInd, qb1), qb2);
+
3996  pairLocalInd = pairGlobalInd - pairGlobalStartInd;
+
3997 
+
3998  reVec[localInd] = rePairVec[pairLocalInd];
+
3999  imVec[localInd] = imPairVec[pairLocalInd];
+
4000  }
+
4001  }
+
4002  }
+
4003 }

References Qureg::chunkId, flipBit(), isOddParity(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, and Qureg::stateVec.

-

Referenced by statevec_swapQubitAmps().

+

Referenced by statevec_swapQubitAmps().

@@ -5286,49 +5315,49 @@

-

Definition at line 3882 of file QuEST_cpu.c.

-
3882  {
-
3883 
-
3884  // can't use qureg.stateVec as a private OMP var
-
3885  qreal *reVec = qureg.stateVec.real;
-
3886  qreal *imVec = qureg.stateVec.imag;
-
3887 
-
3888  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
3889  long long int thisTask;
-
3890  long long int ind00, ind01, ind10;
-
3891  qreal re01, re10;
-
3892  qreal im01, im10;
-
3893 
-
3894 # ifdef _OPENMP
-
3895 # pragma omp parallel \
-
3896  default (none) \
-
3897  shared (reVec,imVec,numTasks,qb1,qb2) \
-
3898  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
-
3899 # endif
-
3900  {
-
3901 # ifdef _OPENMP
-
3902 # pragma omp for schedule (static)
-
3903 # endif
-
3904  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
3905  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
3906  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
3907  ind01 = flipBit(ind00, qb1);
-
3908  ind10 = flipBit(ind00, qb2);
-
3909 
-
3910  // extract statevec amplitudes
-
3911  re01 = reVec[ind01]; im01 = imVec[ind01];
-
3912  re10 = reVec[ind10]; im10 = imVec[ind10];
-
3913 
-
3914  // swap 01 and 10 amps
-
3915  reVec[ind01] = re10; reVec[ind10] = re01;
-
3916  imVec[ind01] = im10; imVec[ind10] = im01;
-
3917  }
-
3918  }
-
3919 }
+

Definition at line 3922 of file QuEST_cpu.c.

+
3922  {
+
3923 
+
3924  // can't use qureg.stateVec as a private OMP var
+
3925  qreal *reVec = qureg.stateVec.real;
+
3926  qreal *imVec = qureg.stateVec.imag;
+
3927 
+
3928  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
+
3929  long long int thisTask;
+
3930  long long int ind00, ind01, ind10;
+
3931  qreal re01, re10;
+
3932  qreal im01, im10;
+
3933 
+
3934 # ifdef _OPENMP
+
3935 # pragma omp parallel \
+
3936  default (none) \
+
3937  shared (reVec,imVec,numTasks,qb1,qb2) \
+
3938  private (thisTask, ind00,ind01,ind10, re01,re10, im01,im10)
+
3939 # endif
+
3940  {
+
3941 # ifdef _OPENMP
+
3942 # pragma omp for schedule (static)
+
3943 # endif
+
3944  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
3945  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
+
3946  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
+
3947  ind01 = flipBit(ind00, qb1);
+
3948  ind10 = flipBit(ind00, qb2);
+
3949 
+
3950  // extract statevec amplitudes
+
3951  re01 = reVec[ind01]; im01 = imVec[ind01];
+
3952  re10 = reVec[ind10]; im10 = imVec[ind10];
+
3953 
+
3954  // swap 01 and 10 amps
+
3955  reVec[ind01] = re10; reVec[ind10] = re01;
+
3956  imVec[ind01] = im10; imVec[ind10] = im01;
+
3957  }
+
3958  }
+
3959 }

References flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by statevec_swapQubitAmps().

+

Referenced by statevec_swapQubitAmps().

@@ -5397,50 +5426,50 @@

Definition at line 2112 of file QuEST_cpu.c.

-
2117 {
-
2118 
-
2119  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
2120  long long int thisTask;
-
2121  long long int numTasks=qureg.numAmpsPerChunk;
-
2122 
-
2123  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
-
2124  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
-
2125  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
-
2126  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
-
2127  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
-
2128 
-
2129 
-
2130 # ifdef _OPENMP
-
2131 # pragma omp parallel \
-
2132  default (none) \
-
2133  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
-
2134  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
-
2135  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2136 # endif
-
2137  {
-
2138 # ifdef _OPENMP
-
2139 # pragma omp for schedule (static)
-
2140 # endif
-
2141  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2142  // store current state vector values in temp variables
-
2143  stateRealUp = stateVecRealUp[thisTask];
-
2144  stateImagUp = stateVecImagUp[thisTask];
-
2145 
-
2146  stateRealLo = stateVecRealLo[thisTask];
-
2147  stateImagLo = stateVecImagLo[thisTask];
-
2148 
-
2149  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
-
2150  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
-
2151  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
-
2152  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
-
2153  }
-
2154  }
-
2155 }
+

Definition at line 2151 of file QuEST_cpu.c.

+
2156 {
+
2157 
+
2158  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2159  long long int thisTask;
+
2160  long long int numTasks=qureg.numAmpsPerChunk;
+
2161 
+
2162  qreal rot1Real=rot1.real, rot1Imag=rot1.imag;
+
2163  qreal rot2Real=rot2.real, rot2Imag=rot2.imag;
+
2164  qreal *stateVecRealUp=stateVecUp.real, *stateVecImagUp=stateVecUp.imag;
+
2165  qreal *stateVecRealLo=stateVecLo.real, *stateVecImagLo=stateVecLo.imag;
+
2166  qreal *stateVecRealOut=stateVecOut.real, *stateVecImagOut=stateVecOut.imag;
+
2167 
+
2168 
+
2169 # ifdef _OPENMP
+
2170 # pragma omp parallel \
+
2171  default (none) \
+
2172  shared (stateVecRealUp,stateVecImagUp,stateVecRealLo,stateVecImagLo,stateVecRealOut,stateVecImagOut, \
+
2173  rot1Real, rot1Imag, rot2Real, rot2Imag,numTasks) \
+
2174  private (thisTask,stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2175 # endif
+
2176  {
+
2177 # ifdef _OPENMP
+
2178 # pragma omp for schedule (static)
+
2179 # endif
+
2180  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2181  // store current state vector values in temp variables
+
2182  stateRealUp = stateVecRealUp[thisTask];
+
2183  stateImagUp = stateVecImagUp[thisTask];
+
2184 
+
2185  stateRealLo = stateVecRealLo[thisTask];
+
2186  stateImagLo = stateVecImagLo[thisTask];
+
2187 
+
2188  stateVecRealOut[thisTask] = rot1Real*stateRealUp - rot1Imag*stateImagUp
+
2189  + rot2Real*stateRealLo - rot2Imag*stateImagLo;
+
2190  stateVecImagOut[thisTask] = rot1Real*stateImagUp + rot1Imag*stateRealUp
+
2191  + rot2Real*stateImagLo + rot2Imag*stateRealLo;
+
2192  }
+
2193  }
+
2194 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_unitary().

+

Referenced by statevec_unitary().

@@ -5476,75 +5505,75 @@

-

Definition at line 1987 of file QuEST_cpu.c.

-
1988 {
-
1989  long long int sizeBlock, sizeHalfBlock;
-
1990  long long int thisBlock, // current block
-
1991  indexUp,indexLo; // current index and corresponding index in lower half block
-
1992 
-
1993  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
-
1994  long long int thisTask;
-
1995  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1996 
-
1997  // set dimensions
-
1998  sizeHalfBlock = 1LL << targetQubit;
-
1999  sizeBlock = 2LL * sizeHalfBlock;
-
2000 
-
2001  // Can't use qureg.stateVec as a private OMP var
-
2002  qreal *stateVecReal = qureg.stateVec.real;
-
2003  qreal *stateVecImag = qureg.stateVec.imag;
-
2004 
-
2005 # ifdef _OPENMP
-
2006 # pragma omp parallel \
-
2007  default (none) \
-
2008  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
-
2009  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
-
2010 # endif
-
2011  {
-
2012 # ifdef _OPENMP
-
2013 # pragma omp for schedule (static)
-
2014 # endif
-
2015  for (thisTask=0; thisTask<numTasks; thisTask++) {
-
2016 
-
2017  thisBlock = thisTask / sizeHalfBlock;
-
2018  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2019  indexLo = indexUp + sizeHalfBlock;
-
2020 
-
2021  // store current state vector values in temp variables
-
2022  stateRealUp = stateVecReal[indexUp];
-
2023  stateImagUp = stateVecImag[indexUp];
-
2024 
-
2025  stateRealLo = stateVecReal[indexLo];
-
2026  stateImagLo = stateVecImag[indexLo];
-
2027 
-
2028 
-
2029  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
2030  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
-
2031  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
-
2032  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
-
2033  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
-
2034 
-
2035  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
2036  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
-
2037  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
-
2038  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
-
2039  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
-
2040 
-
2041  }
-
2042  }
-
2043 }
+

Definition at line 2026 of file QuEST_cpu.c.

+
2027 {
+
2028  long long int sizeBlock, sizeHalfBlock;
+
2029  long long int thisBlock, // current block
+
2030  indexUp,indexLo; // current index and corresponding index in lower half block
+
2031 
+
2032  qreal stateRealUp,stateRealLo,stateImagUp,stateImagLo;
+
2033  long long int thisTask;
+
2034  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2035 
+
2036  // set dimensions
+
2037  sizeHalfBlock = 1LL << targetQubit;
+
2038  sizeBlock = 2LL * sizeHalfBlock;
+
2039 
+
2040  // Can't use qureg.stateVec as a private OMP var
+
2041  qreal *stateVecReal = qureg.stateVec.real;
+
2042  qreal *stateVecImag = qureg.stateVec.imag;
+
2043 
+
2044 # ifdef _OPENMP
+
2045 # pragma omp parallel \
+
2046  default (none) \
+
2047  shared (sizeBlock,sizeHalfBlock, stateVecReal,stateVecImag, u,numTasks) \
+
2048  private (thisTask,thisBlock ,indexUp,indexLo, stateRealUp,stateImagUp,stateRealLo,stateImagLo)
+
2049 # endif
+
2050  {
+
2051 # ifdef _OPENMP
+
2052 # pragma omp for schedule (static)
+
2053 # endif
+
2054  for (thisTask=0; thisTask<numTasks; thisTask++) {
+
2055 
+
2056  thisBlock = thisTask / sizeHalfBlock;
+
2057  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2058  indexLo = indexUp + sizeHalfBlock;
+
2059 
+
2060  // store current state vector values in temp variables
+
2061  stateRealUp = stateVecReal[indexUp];
+
2062  stateImagUp = stateVecImag[indexUp];
+
2063 
+
2064  stateRealLo = stateVecReal[indexLo];
+
2065  stateImagLo = stateVecImag[indexLo];
+
2066 
+
2067 
+
2068  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
2069  stateVecReal[indexUp] = u.real[0][0]*stateRealUp - u.imag[0][0]*stateImagUp
+
2070  + u.real[0][1]*stateRealLo - u.imag[0][1]*stateImagLo;
+
2071  stateVecImag[indexUp] = u.real[0][0]*stateImagUp + u.imag[0][0]*stateRealUp
+
2072  + u.real[0][1]*stateImagLo + u.imag[0][1]*stateRealLo;
+
2073 
+
2074  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
2075  stateVecReal[indexLo] = u.real[1][0]*stateRealUp - u.imag[1][0]*stateImagUp
+
2076  + u.real[1][1]*stateRealLo - u.imag[1][1]*stateImagLo;
+
2077  stateVecImag[indexLo] = u.real[1][0]*stateImagUp + u.imag[1][0]*stateRealUp
+
2078  + u.real[1][1]*stateImagLo + u.imag[1][1]*stateRealLo;
+
2079 
+
2080  }
+
2081  }
+
2082 }

References ComplexMatrix2::imag, Qureg::numAmpsPerChunk, qreal, ComplexMatrix2::real, and Qureg::stateVec.

-

Referenced by statevec_unitary().

+

Referenced by statevec_unitary().

-
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1897
+
int qsortComp(const void *a, const void *b)
Definition: QuEST_cpu.c:1908
qreal real[4][4]
Definition: QuEST.h:177
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:85
#define qreal
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
static int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
@@ -5553,7 +5582,7 @@

__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
+
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:54
qreal imag[4][4]
Definition: QuEST.h:178
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
qreal ** real
Definition: QuEST.h:189
diff --git a/docs/QuEST__cpu__internal_8h_source.html b/docs/QuEST__cpu__internal_8h_source.html index edf26e34b..4abda5478 100644 --- a/docs/QuEST__cpu__internal_8h_source.html +++ b/docs/QuEST__cpu__internal_8h_source.html @@ -27,7 +27,7 @@ @@ -257,70 +257,70 @@
207 
208 # endif // QUEST_CPU_INTERNAL_H
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3925
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFactor)
Definition: QuEST_cpu.c:2997
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:547
+
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3965
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFactor)
Definition: QuEST_cpu.c:3036
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
+
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:306
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
#define qreal
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2112
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2151
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
static long long int flipBit(const long long int number, const int bitInd)
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2703
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFactor)
Definition: QuEST_cpu.c:2943
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
+
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2742
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFactor)
Definition: QuEST_cpu.c:2982
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
static int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3100
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3474
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
-
void statevec_calcProbOfAllOutcomesLocal(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3847
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3809
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2437
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2503
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2906
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
+
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3139
+
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3513
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
+
void statevec_calcProbOfAllOutcomesLocal(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
+
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3887
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
+
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3849
+
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:230
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
+
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2476
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
+
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2542
+
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2945
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
+
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:638
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
Represents a system of qubits.
Definition: QuEST.h:322
-
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2795
+
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2834
static long long int insertZeroBit(const long long int number, const int index)
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
static int isOddParity(const long long int number, const int qb1, const int qb2)
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2375
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2414
+
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:494
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
static int maskContainsBit(const long long int mask, const int bitInd)
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2612
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2056
+
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2651
+
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2095
static long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
diff --git a/docs/QuEST__cpu__local_8c.html b/docs/QuEST__cpu__local_8c.html index 99833194b..fcf096b50 100644 --- a/docs/QuEST__cpu__local_8c.html +++ b/docs/QuEST__cpu__local_8c.html @@ -27,7 +27,7 @@ @@ -113,9 +113,9 @@ void reportQuESTEnv (QuESTEnv env)  Report information about the QuEST environment. More...
  -void seedQuESTDefault (void) - Seed the Mersenne Twister used for random number generation in the QuEST environment with an example default seed. More...
-  +void seedQuEST (QuESTEnv *env, unsigned long int *seedArray, int numSeeds) + Seeds the random number generator with a custom array of key(s), overriding the default keys. More...
Complex statevec_calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)   Complex statevec_calcInnerProduct (Qureg bra, Qureg ket) @@ -209,23 +209,23 @@

-

Definition at line 350 of file QuEST_cpu_local.c.

-
350  {
-
351 
-
352  // we must preload qureg.pairStateVec with the elements of op.
-
353  // instead of needless cloning, we'll just temporarily swap the pointers
-
354  qreal* rePtr = qureg.pairStateVec.real;
-
355  qreal* imPtr = qureg.pairStateVec.imag;
-
356  qureg.pairStateVec.real = op.real;
-
357  qureg.pairStateVec.imag = op.imag;
-
358 
- -
360 
-
361  qureg.pairStateVec.real = rePtr;
-
362  qureg.pairStateVec.imag = imPtr;
-
363 }
+

Definition at line 358 of file QuEST_cpu_local.c.

+
358  {
+
359 
+
360  // we must preload qureg.pairStateVec with the elements of op.
+
361  // instead of needless cloning, we'll just temporarily swap the pointers
+
362  qreal* rePtr = qureg.pairStateVec.real;
+
363  qreal* imPtr = qureg.pairStateVec.imag;
+
364  qureg.pairStateVec.real = op.real;
+
365  qureg.pairStateVec.imag = op.imag;
+
366 
+ +
368 
+
369  qureg.pairStateVec.real = rePtr;
+
370  qureg.pairStateVec.imag = imPtr;
+
371 }
-

References densmatr_applyDiagonalOpLocal(), DiagonalOp::imag, Qureg::pairStateVec, qreal, and DiagonalOp::real.

+

References densmatr_applyDiagonalOpLocal(), DiagonalOp::imag, Qureg::pairStateVec, qreal, and DiagonalOp::real.

@@ -255,13 +255,13 @@

-

Definition at line 370 of file QuEST_cpu_local.c.

-
370  {
-
371 
-
372  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
373 }
+

Definition at line 378 of file QuEST_cpu_local.c.

+
378  {
+
379 
+
380  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
+
381 }
-

References densmatr_calcExpecDiagonalOpLocal().

+

References densmatr_calcExpecDiagonalOpLocal().

@@ -312,7 +312,7 @@

92  return fid;
93 }
-

References densmatr_calcFidelityLocal(), Qureg::pairStateVec, qreal, and Qureg::stateVec.

+

References densmatr_calcFidelityLocal(), Qureg::pairStateVec, qreal, and Qureg::stateVec.

@@ -350,7 +350,7 @@

66  return dist;
67 }
-

References densmatr_calcHilbertSchmidtDistanceSquaredLocal(), and qreal.

+

References densmatr_calcHilbertSchmidtDistanceSquaredLocal(), and qreal.

@@ -387,7 +387,7 @@

72  return scalar;
73 }
-

References densmatr_calcInnerProductLocal(), and qreal.

+

References densmatr_calcInnerProductLocal(), and qreal.

@@ -429,13 +429,13 @@

-

Definition at line 315 of file QuEST_cpu_local.c.

-
315  {
-
316 
-
317  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
318 }
+

Definition at line 317 of file QuEST_cpu_local.c.

+
317  {
+
318 
+
319  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
320 }
-

References densmatr_calcProbOfAllOutcomesLocal().

+

References densmatr_calcProbOfAllOutcomesLocal().

@@ -471,16 +471,16 @@

-

Definition at line 302 of file QuEST_cpu_local.c.

-
302  {
-
303 
-
304  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
305  if (outcome == 1)
-
306  outcomeProb = 1.0 - outcomeProb;
-
307  return outcomeProb;
-
308 }
+

Definition at line 304 of file QuEST_cpu_local.c.

+
304  {
+
305 
+
306  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
+
307  if (outcome == 1)
+
308  outcomeProb = 1.0 - outcomeProb;
+
309  return outcomeProb;
+
310 }
-

References densmatr_findProbabilityOfZeroLocal(), and qreal.

+

References densmatr_findProbabilityOfZeroLocal(), and qreal.

@@ -506,7 +506,7 @@

59  return densmatr_calcPurityLocal(qureg);
60 }
-

References densmatr_calcPurityLocal().

+

References densmatr_calcPurityLocal().

@@ -599,7 +599,7 @@

110  qureg.pairStateVec.imag = quregPairImPtr;
111 }
-

References densmatr_initPureStateLocal(), Qureg::pairStateVec, qreal, and Qureg::stateVec.

+

References densmatr_initPureStateLocal(), Qureg::pairStateVec, qreal, and Qureg::stateVec.

@@ -643,7 +643,7 @@

41  densmatr_mixDampingLocal(qureg, targetQubit, damping);
42 }
-

References densmatr_mixDampingLocal().

+

References densmatr_mixDampingLocal().

@@ -687,7 +687,7 @@

34  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
35 }
-

References densmatr_mixDepolarisingLocal().

+

References densmatr_mixDepolarisingLocal().

@@ -743,7 +743,7 @@

54  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
55 }
-

References densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingLocal(), and qreal.

+

References densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingLocal(), and qreal.

@@ -773,13 +773,13 @@

-

Definition at line 365 of file QuEST_cpu_local.c.

-
365  {
-
366 
-
367  return statevec_calcExpecDiagonalOpLocal(qureg, op);
-
368 }
+

Definition at line 373 of file QuEST_cpu_local.c.

+
373  {
+
374 
+
375  return statevec_calcExpecDiagonalOpLocal(qureg, op);
+
376 }
-

References statevec_calcExpecDiagonalOpLocal().

+

References statevec_calcExpecDiagonalOpLocal().

@@ -815,7 +815,7 @@

115  return statevec_calcInnerProductLocal(bra, ket);
116 }
-

References statevec_calcInnerProductLocal().

+

References statevec_calcInnerProductLocal().

@@ -857,13 +857,13 @@

-

Definition at line 310 of file QuEST_cpu_local.c.

-
310  {
-
311 
-
312  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
313 }
+

Definition at line 312 of file QuEST_cpu_local.c.

+
312  {
+
313 
+
314  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
315 }
-

References statevec_calcProbOfAllOutcomesLocal().

+

References statevec_calcProbOfAllOutcomesLocal().

@@ -899,15 +899,15 @@

-

Definition at line 294 of file QuEST_cpu_local.c.

-
295 {
-
296  qreal outcomeProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
297  if (outcome==1)
-
298  outcomeProb = 1.0 - outcomeProb;
-
299  return outcomeProb;
-
300 }
+

Definition at line 296 of file QuEST_cpu_local.c.

+
297 {
+
298  qreal outcomeProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
+
299  if (outcome==1)
+
300  outcomeProb = 1.0 - outcomeProb;
+
301  return outcomeProb;
+
302 }
-

References qreal, and statevec_findProbabilityOfZeroLocal().

+

References qreal, and statevec_findProbabilityOfZeroLocal().

@@ -998,12 +998,12 @@

-

Definition at line 320 of file QuEST_cpu_local.c.

-
321 {
-
322  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
-
323 }
+

Definition at line 322 of file QuEST_cpu_local.c.

+
323 {
+
324  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
+
325 }
-

References statevec_collapseToKnownProbOutcomeLocal().

+

References statevec_collapseToKnownProbOutcomeLocal().

@@ -1045,12 +1045,12 @@

-

Definition at line 225 of file QuEST_cpu_local.c.

-
226 {
-
227  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
228 }
+

Definition at line 227 of file QuEST_cpu_local.c.

+
228 {
+
229  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
+
230 }
-

References statevec_compactUnitaryLocal().

+

References statevec_compactUnitaryLocal().

@@ -1098,12 +1098,12 @@

-

Definition at line 235 of file QuEST_cpu_local.c.

-
236 {
-
237  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
238 }
+

Definition at line 237 of file QuEST_cpu_local.c.

+
238 {
+
239  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
+
240 }
-

References statevec_controlledCompactUnitaryLocal().

+

References statevec_controlledCompactUnitaryLocal().

@@ -1139,12 +1139,12 @@

-

Definition at line 284 of file QuEST_cpu_local.c.

-
285 {
-
286  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
287 }
+

Definition at line 286 of file QuEST_cpu_local.c.

+
287 {
+
288  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
+
289 }
-

References statevec_controlledNotLocal().

+

References statevec_controlledNotLocal().

@@ -1180,13 +1180,13 @@

-

Definition at line 267 of file QuEST_cpu_local.c.

-
268 {
-
269  int conjFac = 1;
-
270  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
271 }
+

Definition at line 269 of file QuEST_cpu_local.c.

+
270 {
+
271  int conjFac = 1;
+
272  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
273 }
-

References statevec_controlledPauliYLocal().

+

References statevec_controlledPauliYLocal().

@@ -1222,13 +1222,13 @@

-

Definition at line 273 of file QuEST_cpu_local.c.

-
274 {
-
275  int conjFac = -1;
-
276  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
277 }
+

Definition at line 275 of file QuEST_cpu_local.c.

+
276 {
+
277  int conjFac = -1;
+
278  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
279 }
-

References statevec_controlledPauliYLocal().

+

References statevec_controlledPauliYLocal().

@@ -1270,12 +1270,12 @@

-

Definition at line 240 of file QuEST_cpu_local.c.

-
241 {
-
242  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
243 }
+

Definition at line 242 of file QuEST_cpu_local.c.

+
243 {
+
244  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
+
245 }
-

References statevec_controlledUnitaryLocal().

+

References statevec_controlledUnitaryLocal().

@@ -1305,10 +1305,10 @@

-

Definition at line 221 of file QuEST_cpu_local.c.

-
221  {
-
222  return qureg.stateVec.imag[index];
-
223 }
+

Definition at line 223 of file QuEST_cpu_local.c.

+
223  {
+
224  return qureg.stateVec.imag[index];
+
225 }

References Qureg::stateVec.

@@ -1340,10 +1340,10 @@

-

Definition at line 217 of file QuEST_cpu_local.c.

-
217  {
-
218  return qureg.stateVec.real[index];
-
219 }
+

Definition at line 219 of file QuEST_cpu_local.c.

+
219  {
+
220  return qureg.stateVec.real[index];
+
221 }

References Qureg::stateVec.

@@ -1375,12 +1375,12 @@

-

Definition at line 279 of file QuEST_cpu_local.c.

-
280 {
-
281  statevec_hadamardLocal(qureg, targetQubit);
-
282 }
+

Definition at line 281 of file QuEST_cpu_local.c.

+
282 {
+
283  statevec_hadamardLocal(qureg, targetQubit);
+
284 }
-

References statevec_hadamardLocal().

+

References statevec_hadamardLocal().

@@ -1416,13 +1416,13 @@

-

Definition at line 289 of file QuEST_cpu_local.c.

-
289  {
-
290 
-
291  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
-
292 }
+

Definition at line 291 of file QuEST_cpu_local.c.

+
291  {
+
292 
+
293  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
+
294 }
-

References statevec_multiControlledMultiQubitNotLocal().

+

References statevec_multiControlledMultiQubitNotLocal().

@@ -1474,12 +1474,12 @@

Todo:
refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.
-

Definition at line 340 of file QuEST_cpu_local.c.

-
341 {
-
342  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
-
343 }
+

Definition at line 348 of file QuEST_cpu_local.c.

+
349 {
+
350  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
+
351 }
-

References statevec_multiControlledMultiQubitUnitaryLocal().

+

References statevec_multiControlledMultiQubitUnitaryLocal().

@@ -1533,12 +1533,12 @@

the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

-

Definition at line 335 of file QuEST_cpu_local.c.

-
336 {
-
337  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
338 }
+

Definition at line 343 of file QuEST_cpu_local.c.

+
344 {
+
345  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
+
346 }
-

References statevec_multiControlledTwoQubitUnitaryLocal().

+

References statevec_multiControlledTwoQubitUnitaryLocal().

@@ -1586,12 +1586,12 @@

-

Definition at line 245 of file QuEST_cpu_local.c.

-
246 {
-
247  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
248 }
+

Definition at line 247 of file QuEST_cpu_local.c.

+
248 {
+
249  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
+
250 }
-

References statevec_multiControlledUnitaryLocal().

+

References statevec_multiControlledUnitaryLocal().

@@ -1621,12 +1621,12 @@

-

Definition at line 250 of file QuEST_cpu_local.c.

-
251 {
-
252  statevec_pauliXLocal(qureg, targetQubit);
-
253 }
+

Definition at line 252 of file QuEST_cpu_local.c.

+
253 {
+
254  statevec_pauliXLocal(qureg, targetQubit);
+
255 }
-

References statevec_pauliXLocal().

+

References statevec_pauliXLocal().

@@ -1656,13 +1656,13 @@

-

Definition at line 255 of file QuEST_cpu_local.c.

-
256 {
-
257  int conjFac = 1;
-
258  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
259 }
+

Definition at line 257 of file QuEST_cpu_local.c.

+
258 {
+
259  int conjFac = 1;
+
260  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
261 }
-

References statevec_pauliYLocal().

+

References statevec_pauliYLocal().

@@ -1692,13 +1692,13 @@

-

Definition at line 261 of file QuEST_cpu_local.c.

-
262 {
-
263  int conjFac = -1;
-
264  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
265 }
+

Definition at line 263 of file QuEST_cpu_local.c.

+
264 {
+
265  int conjFac = -1;
+
266  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
267 }
-

References statevec_pauliYLocal().

+

References statevec_pauliYLocal().

@@ -1734,12 +1734,12 @@

-

Definition at line 345 of file QuEST_cpu_local.c.

-
346 {
-
347  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
348 }
+

Definition at line 353 of file QuEST_cpu_local.c.

+
354 {
+
355  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
+
356 }
-

References statevec_swapQubitAmpsLocal().

+

References statevec_swapQubitAmpsLocal().

@@ -1775,55 +1775,55 @@

-

Definition at line 230 of file QuEST_cpu_local.c.

-
231 {
-
232  statevec_unitaryLocal(qureg, targetQubit, u);
-
233 }
+

Definition at line 232 of file QuEST_cpu_local.c.

+
233 {
+
234  statevec_unitaryLocal(qureg, targetQubit, u);
+
235 }
-

References statevec_unitaryLocal().

+

References statevec_unitaryLocal().

-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
#define qreal
-
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
+
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2943
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
diff --git a/docs/QuEST__cpu__local_8c_source.html b/docs/QuEST__cpu__local_8c_source.html index b4df223a5..9175451e0 100644 --- a/docs/QuEST__cpu__local_8c_source.html +++ b/docs/QuEST__cpu__local_8c_source.html @@ -27,7 +27,7 @@ @@ -225,303 +225,313 @@
174  env.rank=0;
175  env.numRanks=1;
176 
- -
178 
-
179  return env;
-
180 }
-
181 
- -
183  // MPI Barrier goes here in MPI version.
-
184 }
-
185 
-
186 int syncQuESTSuccess(int successCode){
-
187  return successCode;
-
188 }
-
189 
- -
191  // MPI finalize goes here in MPI version. Call this function anyway for consistency
-
192 }
-
193 
- -
195  printf("EXECUTION ENVIRONMENT:\n");
-
196  printf("Running locally on one node\n");
-
197  printf("Number of ranks is %d\n", env.numRanks);
-
198 # ifdef _OPENMP
-
199  printf("OpenMP enabled\n");
-
200  printf("Number of threads available is %d\n", omp_get_max_threads());
-
201 # else
-
202  printf("OpenMP disabled\n");
-
203 # endif
-
204  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal));
-
205 }
-
206 
-
207 void getEnvironmentString(QuESTEnv env, char str[200]){
-
208  int ompStatus=0;
-
209  int numThreads=1;
-
210 # ifdef _OPENMP
-
211  ompStatus=1;
-
212  numThreads=omp_get_max_threads();
-
213 # endif
-
214  sprintf(str, "CUDA=0 OpenMP=%d MPI=0 threads=%d ranks=1", ompStatus, numThreads);
-
215 }
-
216 
-
217 qreal statevec_getRealAmp(Qureg qureg, long long int index){
-
218  return qureg.stateVec.real[index];
-
219 }
-
220 
-
221 qreal statevec_getImagAmp(Qureg qureg, long long int index){
-
222  return qureg.stateVec.imag[index];
-
223 }
-
224 
-
225 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
226 {
-
227  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
228 }
-
229 
-
230 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
231 {
-
232  statevec_unitaryLocal(qureg, targetQubit, u);
-
233 }
-
234 
-
235 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
236 {
-
237  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
238 }
-
239 
-
240 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
241 {
-
242  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
243 }
-
244 
-
245 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
246 {
-
247  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
248 }
-
249 
-
250 void statevec_pauliX(Qureg qureg, int targetQubit)
-
251 {
-
252  statevec_pauliXLocal(qureg, targetQubit);
-
253 }
-
254 
-
255 void statevec_pauliY(Qureg qureg, int targetQubit)
-
256 {
-
257  int conjFac = 1;
-
258  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
259 }
-
260 
-
261 void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
262 {
-
263  int conjFac = -1;
-
264  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
265 }
-
266 
-
267 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
268 {
-
269  int conjFac = 1;
-
270  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
271 }
-
272 
-
273 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
274 {
-
275  int conjFac = -1;
-
276  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
277 }
-
278 
-
279 void statevec_hadamard(Qureg qureg, int targetQubit)
-
280 {
-
281  statevec_hadamardLocal(qureg, targetQubit);
-
282 }
-
283 
-
284 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
285 {
-
286  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
287 }
-
288 
-
289 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) {
-
290 
-
291  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
-
292 }
-
293 
-
294 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
295 {
-
296  qreal outcomeProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
297  if (outcome==1)
-
298  outcomeProb = 1.0 - outcomeProb;
-
299  return outcomeProb;
-
300 }
-
301 
-
302 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
-
303 
-
304  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
305  if (outcome == 1)
-
306  outcomeProb = 1.0 - outcomeProb;
-
307  return outcomeProb;
-
308 }
-
309 
-
310 void statevec_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
-
311 
-
312  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
313 }
-
314 
-
315 void densmatr_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
-
316 
-
317  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
318 }
-
319 
-
320 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
-
321 {
-
322  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
-
323 }
-
324 
-
325 void seedQuESTDefault(void){
-
326  // init MT random number generator with three keys -- time and pid
-
327  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
328  // used by the master process
-
329 
-
330  unsigned long int key[2];
- -
332  init_by_array(key, 2);
-
333 }
-
334 
-
335 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
-
336 {
-
337  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
338 }
-
339 
-
340 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
-
341 {
-
342  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
-
343 }
-
344 
-
345 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
346 {
-
347  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
348 }
-
349 
- -
351 
-
352  // we must preload qureg.pairStateVec with the elements of op.
-
353  // instead of needless cloning, we'll just temporarily swap the pointers
-
354  qreal* rePtr = qureg.pairStateVec.real;
-
355  qreal* imPtr = qureg.pairStateVec.imag;
-
356  qureg.pairStateVec.real = op.real;
-
357  qureg.pairStateVec.imag = op.imag;
-
358 
- -
360 
-
361  qureg.pairStateVec.real = rePtr;
-
362  qureg.pairStateVec.imag = imPtr;
-
363 }
-
364 
- -
366 
-
367  return statevec_calcExpecDiagonalOpLocal(qureg, op);
-
368 }
-
369 
- -
371 
-
372  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
373 }
+
177  env.seeds = NULL;
+
178  env.numSeeds = 0;
+
179  seedQuESTDefault(&env);
+
180 
+
181  return env;
+
182 }
+
183 
+ +
185  // MPI Barrier goes here in MPI version.
+
186 }
+
187 
+
188 int syncQuESTSuccess(int successCode){
+
189  return successCode;
+
190 }
+
191 
+ +
193  free(env.seeds);
+
194 }
+
195 
+ +
197  printf("EXECUTION ENVIRONMENT:\n");
+
198  printf("Running locally on one node\n");
+
199  printf("Number of ranks is %d\n", env.numRanks);
+
200 # ifdef _OPENMP
+
201  printf("OpenMP enabled\n");
+
202  printf("Number of threads available is %d\n", omp_get_max_threads());
+
203 # else
+
204  printf("OpenMP disabled\n");
+
205 # endif
+
206  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal));
+
207 }
+
208 
+
209 void getEnvironmentString(QuESTEnv env, char str[200]){
+
210  int ompStatus=0;
+
211  int numThreads=1;
+
212 # ifdef _OPENMP
+
213  ompStatus=1;
+
214  numThreads=omp_get_max_threads();
+
215 # endif
+
216  sprintf(str, "CUDA=0 OpenMP=%d MPI=0 threads=%d ranks=1", ompStatus, numThreads);
+
217 }
+
218 
+
219 qreal statevec_getRealAmp(Qureg qureg, long long int index){
+
220  return qureg.stateVec.real[index];
+
221 }
+
222 
+
223 qreal statevec_getImagAmp(Qureg qureg, long long int index){
+
224  return qureg.stateVec.imag[index];
+
225 }
+
226 
+
227 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
228 {
+
229  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
+
230 }
+
231 
+
232 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
233 {
+
234  statevec_unitaryLocal(qureg, targetQubit, u);
+
235 }
+
236 
+
237 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
238 {
+
239  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
+
240 }
+
241 
+
242 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
+
243 {
+
244  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
+
245 }
+
246 
+
247 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
248 {
+
249  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
+
250 }
+
251 
+
252 void statevec_pauliX(Qureg qureg, int targetQubit)
+
253 {
+
254  statevec_pauliXLocal(qureg, targetQubit);
+
255 }
+
256 
+
257 void statevec_pauliY(Qureg qureg, int targetQubit)
+
258 {
+
259  int conjFac = 1;
+
260  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
261 }
+
262 
+
263 void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
264 {
+
265  int conjFac = -1;
+
266  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
267 }
+
268 
+
269 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
270 {
+
271  int conjFac = 1;
+
272  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
273 }
+
274 
+
275 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
276 {
+
277  int conjFac = -1;
+
278  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
279 }
+
280 
+
281 void statevec_hadamard(Qureg qureg, int targetQubit)
+
282 {
+
283  statevec_hadamardLocal(qureg, targetQubit);
+
284 }
+
285 
+
286 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
287 {
+
288  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
+
289 }
+
290 
+
291 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) {
+
292 
+
293  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
+
294 }
+
295 
+
296 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
297 {
+
298  qreal outcomeProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
+
299  if (outcome==1)
+
300  outcomeProb = 1.0 - outcomeProb;
+
301  return outcomeProb;
+
302 }
+
303 
+
304 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
+
305 
+
306  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
+
307  if (outcome == 1)
+
308  outcomeProb = 1.0 - outcomeProb;
+
309  return outcomeProb;
+
310 }
+
311 
+
312 void statevec_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
+
313 
+
314  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
315 }
+
316 
+
317 void densmatr_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
+
318 
+
319  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
320 }
+
321 
+
322 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
+
323 {
+
324  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
+
325 }
+
326 
+
327 void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds) {
+
328 
+
329  // free existing seed array, if exists
+
330  if (env->seeds != NULL)
+
331  free(env->seeds);
+
332 
+
333  // record keys in permanent heap
+
334  env->seeds = malloc(numSeeds * sizeof *(env->seeds));
+
335  for (int i=0; i<numSeeds; i++)
+
336  (env->seeds)[i] = seedArray[i];
+
337  env->numSeeds = numSeeds;
+
338 
+
339  // pass keys to Mersenne Twister seeder
+
340  init_by_array(seedArray, numSeeds);
+
341 }
+
342 
+
343 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
+
344 {
+
345  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
+
346 }
+
347 
+
348 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
+
349 {
+
350  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
+
351 }
+
352 
+
353 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
354 {
+
355  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
+
356 }
+
357 
+ +
359 
+
360  // we must preload qureg.pairStateVec with the elements of op.
+
361  // instead of needless cloning, we'll just temporarily swap the pointers
+
362  qreal* rePtr = qureg.pairStateVec.real;
+
363  qreal* imPtr = qureg.pairStateVec.imag;
+
364  qureg.pairStateVec.real = op.real;
+
365  qureg.pairStateVec.imag = op.imag;
+
366 
+ +
368 
+
369  qureg.pairStateVec.real = rePtr;
+
370  qureg.pairStateVec.imag = imPtr;
+
371 }
+
372 
+ +
374 
+
375  return statevec_calcExpecDiagonalOpLocal(qureg, op);
+
376 }
+
377 
+ +
379 
+
380  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
+
381 }
qreal densmatr_calcTotalProb(Qureg qureg)
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
-
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
-
int rank
Definition: QuEST.h:363
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
+
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
+
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
+
int rank
Definition: QuEST.h:364
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void seedQuESTDefault(QuESTEnv *env)
Seeds the random number generator with the (master node) current time and process ID.
Definition: QuEST.c:1614
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
int numSeeds
Definition: QuEST.h:367
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
void statevec_hadamard(Qureg qureg, int targetQubit)
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
Information about the environment the program is running in.
Definition: QuEST.h:361
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
+
Information about the environment the program is running in.
Definition: QuEST.h:362
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
#define qreal
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
+
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
void densmatr_initPureState(Qureg qureg, Qureg pureState)
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2943
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
+
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
qreal densmatr_calcPurity(Qureg qureg)
-
int numRanks
Definition: QuEST.h:364
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
+
int numRanks
Definition: QuEST.h:365
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
+
unsigned long int * seeds
Definition: QuEST.h:366
+
void statevec_pauliY(Qureg qureg, int targetQubit)
+
void statevec_pauliX(Qureg qureg, int targetQubit)
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
Represents a system of qubits.
Definition: QuEST.h:322
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
+
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
qreal statevec_calcTotalProb(Qureg qureg)
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void seedQuESTDefault(void)
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
+
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
+
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
Represents one complex number.
Definition: QuEST.h:103
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
+
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
diff --git a/docs/QuEST__debug_8h.html b/docs/QuEST__debug_8h.html index 0908eab24..4c4d49cb0 100644 --- a/docs/QuEST__debug_8h.html +++ b/docs/QuEST__debug_8h.html @@ -27,7 +27,7 @@ @@ -126,13 +126,13 @@

Definition at line 1558 of file QuEST.c.

-
1558  {
-
1559  validateMatchingQuregDims(qureg1, qureg2, __func__);
-
1560  return statevec_compareStates(qureg1, qureg2, precision);
-
1561 }
+

Definition at line 1573 of file QuEST.c.

+
1573  {
+
1574  validateMatchingQuregDims(qureg1, qureg2, __func__);
+
1575  return statevec_compareStates(qureg1, qureg2, precision);
+
1576 }
-

References statevec_compareStates(), and validateMatchingQuregDims().

+

References statevec_compareStates(), and validateMatchingQuregDims().

@@ -197,13 +197,13 @@

Definition at line 1567 of file QuEST.c.

-
1567  {
-
1568  int success = statevec_initStateFromSingleFile(qureg, filename, env);
-
1569  validateFileOpened(success, filename, __func__);
-
1570 }
+

Definition at line 1582 of file QuEST.c.

+
1582  {
+
1583  int success = statevec_initStateFromSingleFile(qureg, filename, env);
+
1584  validateFileOpened(success, filename, __func__);
+
1585 }
-

References statevec_initStateFromSingleFile(), and validateFileOpened().

+

References statevec_initStateFromSingleFile(), and validateFileOpened().

@@ -249,15 +249,15 @@

Definition at line 1572 of file QuEST.c.

-
1572  {
-
1573  validateStateVecQureg(*qureg, __func__);
-
1574  validateTarget(*qureg, qubitId, __func__);
-
1575  validateOutcome(outcome, __func__);
-
1576  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
-
1577 }
+

Definition at line 1587 of file QuEST.c.

+
1587  {
+
1588  validateStateVecQureg(*qureg, __func__);
+
1589  validateTarget(*qureg, qubitId, __func__);
+
1590  validateOutcome(outcome, __func__);
+
1591  statevec_initStateOfSingleQubit(qureg, qubitId, outcome);
+
1592 }
-

References statevec_initStateOfSingleQubit(), validateOutcome(), validateStateVecQureg(), and validateTarget().

+

References statevec_initStateOfSingleQubit(), validateOutcome(), validateStateVecQureg(), and validateTarget().

@@ -316,30 +316,30 @@

Definition at line 1017 of file QuEST.c.

-
1017  {
-
1018  long long int numAmps = qureg.numAmpsTotal;
-
1019  statevec_setAmps(qureg, 0, reals, imags, numAmps);
-
1020 
-
1021  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
-
1022 }
+

Definition at line 1030 of file QuEST.c.

+
1030  {
+
1031  long long int numAmps = qureg.numAmpsTotal;
+
1032  statevec_setAmps(qureg, 0, reals, imags, numAmps);
+
1033 
+
1034  qasm_recordComment(qureg, "Here, some amplitudes in the density matrix were manually edited.");
+
1035 }
-

References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

+

References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1600
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void validateOutcome(int outcome, const char *caller)
+
void validateStateVecQureg(Qureg qureg, const char *caller)
+
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1611
+
void validateFileOpened(int opened, char *fn, const char *caller)
+
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1248
+
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1680
+
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1691
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1730
+
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1741
diff --git a/docs/QuEST__debug_8h_source.html b/docs/QuEST__debug_8h_source.html index 390d2bc9d..a6239ed57 100644 --- a/docs/QuEST__debug_8h_source.html +++ b/docs/QuEST__debug_8h_source.html @@ -27,7 +27,7 @@ @@ -89,16 +89,16 @@
60 
61 # endif // QUEST_DEBUG_H
-
int compareStates(Qureg mq1, Qureg mq2, qreal precision)
Return whether two given wavefunctions are equivalent within a given precision Global phase included ...
Definition: QuEST.c:1558
-
void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Initialises the wavefunction amplitudes according to those specified in a file.
Definition: QuEST.c:1567
-
Information about the environment the program is running in.
Definition: QuEST.h:361
+
int compareStates(Qureg mq1, Qureg mq2, qreal precision)
Return whether two given wavefunctions are equivalent within a given precision Global phase included ...
Definition: QuEST.c:1573
+
void initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Initialises the wavefunction amplitudes according to those specified in a file.
Definition: QuEST.c:1582
+
Information about the environment the program is running in.
Definition: QuEST.h:362
#define qreal
int QuESTPrecision(void)
Return the precision of qreal for use in testing.
-
void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST.c:1572
+
void initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST.c:1587
Represents a system of qubits.
Definition: QuEST.h:322
void initStateDebug(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
-
void setDensityAmps(Qureg qureg, qreal *reals, qreal *imags)
Set elements in the underlying state vector represenation of a density matrix.
Definition: QuEST.c:1017
+
void setDensityAmps(Qureg qureg, qreal *reals, qreal *imags)
Set elements in the underlying state vector represenation of a density matrix.
Definition: QuEST.c:1030
diff --git a/docs/QuEST__gpu_8cu.html b/docs/QuEST__gpu_8cu.html index ba0ba96fe..72f34f571 100644 --- a/docs/QuEST__gpu_8cu.html +++ b/docs/QuEST__gpu_8cu.html @@ -27,7 +27,7 @@ @@ -220,9 +220,9 @@ void reportQuESTEnv (QuESTEnv env)  Report information about the QuEST environment. More...
  -void seedQuESTDefault () - Seed the Mersenne Twister used for random number generation in the QuEST environment with an example default seed. More...
-  +void seedQuEST (QuESTEnv *env, unsigned long int *seedArray, int numSeeds) + Seeds the random number generator with a custom array of key(s), overriding the default keys. More...
+  void statevec_applyDiagonalOp (Qureg qureg, DiagonalOp op)   __global__ void statevec_applyDiagonalOpKernel (Qureg qureg, DiagonalOp op) @@ -520,9 +520,9 @@

372  return op;
373 }
-

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

+

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

-

Referenced by createDiagonalOp(), and createDiagonalOpFromPauliHamilFile().

+

Referenced by createDiagonalOp(), and createDiagonalOpFromPauliHamilFile().

@@ -552,7 +552,7 @@

References DiagonalOp::deviceOperator, DiagonalOp::imag, and DiagonalOp::real.

-

Referenced by destroyDiagonalOp().

+

Referenced by destroyDiagonalOp().

@@ -613,7 +613,7 @@

References DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, qreal, and PauliHamil::termCoeffs.

-

Referenced by createDiagonalOpFromPauliHamilFile(), and initDiagonalOpFromPauliHamil().

+

Referenced by createDiagonalOpFromPauliHamilFile(), and initDiagonalOpFromPauliHamil().

@@ -731,29 +731,29 @@

-

Definition at line 3501 of file QuEST_gpu.cu.

-
3501  {
-
3502 
-
3503  // update both RAM and VRAM, for consistency
-
3504  memcpy(&op.real[startInd], real, numElems * sizeof(qreal));
-
3505  memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal));
-
3506 
-
3507  cudaDeviceSynchronize();
-
3508  cudaMemcpy(
-
3509  op.deviceOperator.real + startInd,
-
3510  real,
-
3511  numElems * sizeof(*(op.deviceOperator.real)),
-
3512  cudaMemcpyHostToDevice);
-
3513  cudaMemcpy(
-
3514  op.deviceOperator.imag + startInd,
-
3515  imag,
-
3516  numElems * sizeof(*(op.deviceOperator.imag)),
-
3517  cudaMemcpyHostToDevice);
-
3518 }
+

Definition at line 3503 of file QuEST_gpu.cu.

+
3503  {
+
3504 
+
3505  // update both RAM and VRAM, for consistency
+
3506  memcpy(&op.real[startInd], real, numElems * sizeof(qreal));
+
3507  memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal));
+
3508 
+
3509  cudaDeviceSynchronize();
+
3510  cudaMemcpy(
+
3511  op.deviceOperator.real + startInd,
+
3512  real,
+
3513  numElems * sizeof(*(op.deviceOperator.real)),
+
3514  cudaMemcpyHostToDevice);
+
3515  cudaMemcpy(
+
3516  op.deviceOperator.imag + startInd,
+
3517  imag,
+
3518  numElems * sizeof(*(op.deviceOperator.imag)),
+
3519  cudaMemcpyHostToDevice);
+
3520 }

References DiagonalOp::deviceOperator, DiagonalOp::imag, qreal, and DiagonalOp::real.

-

Referenced by initDiagonalOp(), and setDiagonalOpElems().

+

Referenced by initDiagonalOp(), and setDiagonalOpElems().

@@ -783,7 +783,7 @@

References DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, and DiagonalOp::real.

-

Referenced by syncDiagonalOp().

+

Referenced by syncDiagonalOp().

@@ -819,19 +819,19 @@

-

Definition at line 1949 of file QuEST_gpu.cu.

-
1949  {
-
1950  extern __shared__ qreal tempReductionArray[];
-
1951  int blockOffset = blockIdx.x*length;
-
1952  tempReductionArray[threadIdx.x*2] = arrayIn[blockOffset + threadIdx.x*2];
-
1953  tempReductionArray[threadIdx.x*2+1] = arrayIn[blockOffset + threadIdx.x*2+1];
-
1954  __syncthreads();
-
1955  reduceBlock(tempReductionArray, reducedArray, length);
-
1956 }
+

Definition at line 1951 of file QuEST_gpu.cu.

+
1951  {
+
1952  extern __shared__ qreal tempReductionArray[];
+
1953  int blockOffset = blockIdx.x*length;
+
1954  tempReductionArray[threadIdx.x*2] = arrayIn[blockOffset + threadIdx.x*2];
+
1955  tempReductionArray[threadIdx.x*2+1] = arrayIn[blockOffset + threadIdx.x*2+1];
+
1956  __syncthreads();
+
1957  reduceBlock(tempReductionArray, reducedArray, length);
+
1958 }
-

References qreal, and reduceBlock().

+

References qreal, and reduceBlock().

-

Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), and statevec_findProbabilityOfZero().

+

Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), and statevec_findProbabilityOfZero().

@@ -861,18 +861,18 @@

-

Definition at line 3238 of file QuEST_gpu.cu.

-
3238  {
-
3239 
-
3240  int threadsPerCUDABlock, CUDABlocks;
-
3241  threadsPerCUDABlock = 128;
-
3242  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
3243  densmatr_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
3244 }
+

Definition at line 3240 of file QuEST_gpu.cu.

+
3240  {
+
3241 
+
3242  int threadsPerCUDABlock, CUDABlocks;
+
3243  threadsPerCUDABlock = 128;
+
3244  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
3245  densmatr_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
+
3246 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by applyDiagonalOp().

+

Referenced by applyDiagonalOp().

@@ -902,29 +902,29 @@

-

Definition at line 3215 of file QuEST_gpu.cu.

-
3215  {
-
3216 
-
3217  // each thread modifies one value; a wasteful and inefficient strategy
-
3218  long long int numTasks = qureg.numAmpsPerChunk;
-
3219  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
3220  if (thisTask >= numTasks) return;
-
3221 
-
3222  qreal* stateRe = qureg.deviceStateVec.real;
-
3223  qreal* stateIm = qureg.deviceStateVec.imag;
-
3224  qreal* opRe = op.deviceOperator.real;
-
3225  qreal* opIm = op.deviceOperator.imag;
-
3226 
-
3227  int opDim = (1 << op.numQubits);
-
3228  qreal a = stateRe[thisTask];
-
3229  qreal b = stateIm[thisTask];
-
3230  qreal c = opRe[thisTask % opDim];
-
3231  qreal d = opIm[thisTask % opDim];
-
3232 
-
3233  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3234  stateRe[thisTask] = a*c - b*d;
-
3235  stateIm[thisTask] = a*d + b*c;
-
3236 }
+

Definition at line 3217 of file QuEST_gpu.cu.

+
3217  {
+
3218 
+
3219  // each thread modifies one value; a wasteful and inefficient strategy
+
3220  long long int numTasks = qureg.numAmpsPerChunk;
+
3221  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
3222  if (thisTask >= numTasks) return;
+
3223 
+
3224  qreal* stateRe = qureg.deviceStateVec.real;
+
3225  qreal* stateIm = qureg.deviceStateVec.imag;
+
3226  qreal* opRe = op.deviceOperator.real;
+
3227  qreal* opIm = op.deviceOperator.imag;
+
3228 
+
3229  int opDim = (1 << op.numQubits);
+
3230  qreal a = stateRe[thisTask];
+
3231  qreal b = stateIm[thisTask];
+
3232  qreal c = opRe[thisTask % opDim];
+
3233  qreal d = opIm[thisTask % opDim];
+
3234 
+
3235  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
3236  stateRe[thisTask] = a*c - b*d;
+
3237  stateIm[thisTask] = a*d + b*c;
+
3238 }

References DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, DiagonalOp::numQubits, and qreal.

@@ -956,101 +956,101 @@

-

Definition at line 3410 of file QuEST_gpu.cu.

-
3410  {
-
3411 
-
3412  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3413  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3414  */
-
3415 
-
3416  qreal expecReal, expecImag;
-
3417 
-
3418  int getRealComp;
-
3419  long long int numValuesToReduce;
-
3420  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3421  int maxReducedPerLevel;
-
3422  int firstTime;
-
3423 
-
3424  // compute real component of inner product
-
3425  getRealComp = 1;
-
3426  numValuesToReduce = qureg.numAmpsPerChunk;
-
3427  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3428  firstTime = 1;
-
3429  while (numValuesToReduce > 1) {
-
3430  if (numValuesToReduce < maxReducedPerLevel) {
-
3431  valuesPerCUDABlock = numValuesToReduce;
-
3432  numCUDABlocks = 1;
-
3433  }
-
3434  else {
-
3435  valuesPerCUDABlock = maxReducedPerLevel;
-
3436  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3437  }
-
3438  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3439  if (firstTime) {
-
3440  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3441  getRealComp,
-
3442  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3443  op.deviceOperator.real, op.deviceOperator.imag,
-
3444  op.numQubits, numValuesToReduce,
-
3445  qureg.firstLevelReduction);
-
3446  firstTime = 0;
-
3447  } else {
-
3448  cudaDeviceSynchronize();
-
3449  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3450  qureg.firstLevelReduction,
-
3451  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3452  cudaDeviceSynchronize();
- -
3454  }
-
3455  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3456  }
-
3457  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3458 
-
3459  // compute imag component of inner product
-
3460  getRealComp = 0;
-
3461  numValuesToReduce = qureg.numAmpsPerChunk;
-
3462  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3463  firstTime = 1;
-
3464  while (numValuesToReduce > 1) {
-
3465  if (numValuesToReduce < maxReducedPerLevel) {
-
3466  valuesPerCUDABlock = numValuesToReduce;
-
3467  numCUDABlocks = 1;
-
3468  }
-
3469  else {
-
3470  valuesPerCUDABlock = maxReducedPerLevel;
-
3471  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3472  }
-
3473  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3474  if (firstTime) {
-
3475  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3476  getRealComp,
-
3477  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3478  op.deviceOperator.real, op.deviceOperator.imag,
-
3479  op.numQubits, numValuesToReduce,
-
3480  qureg.firstLevelReduction);
-
3481  firstTime = 0;
-
3482  } else {
-
3483  cudaDeviceSynchronize();
-
3484  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3485  qureg.firstLevelReduction,
-
3486  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3487  cudaDeviceSynchronize();
- -
3489  }
-
3490  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3491  }
-
3492  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3493 
-
3494  // return complex
-
3495  Complex expecVal;
-
3496  expecVal.real = expecReal;
-
3497  expecVal.imag = expecImag;
-
3498  return expecVal;
-
3499 }
-
-

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, DiagonalOp::numQubits, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcExpecDiagonalOp().

+

Definition at line 3412 of file QuEST_gpu.cu.

+
3412  {
+
3413 
+
3414  /* @TODO: remove all this reduction boilerplate from QuEST GPU
+
3415  * (e.g. a func which accepts a pointer to do every-value reduction?)
+
3416  */
+
3417 
+
3418  qreal expecReal, expecImag;
+
3419 
+
3420  int getRealComp;
+
3421  long long int numValuesToReduce;
+
3422  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
3423  int maxReducedPerLevel;
+
3424  int firstTime;
+
3425 
+
3426  // compute real component of inner product
+
3427  getRealComp = 1;
+
3428  numValuesToReduce = qureg.numAmpsPerChunk;
+
3429  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3430  firstTime = 1;
+
3431  while (numValuesToReduce > 1) {
+
3432  if (numValuesToReduce < maxReducedPerLevel) {
+
3433  valuesPerCUDABlock = numValuesToReduce;
+
3434  numCUDABlocks = 1;
+
3435  }
+
3436  else {
+
3437  valuesPerCUDABlock = maxReducedPerLevel;
+
3438  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3439  }
+
3440  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3441  if (firstTime) {
+
3442  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3443  getRealComp,
+
3444  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3445  op.deviceOperator.real, op.deviceOperator.imag,
+
3446  op.numQubits, numValuesToReduce,
+
3447  qureg.firstLevelReduction);
+
3448  firstTime = 0;
+
3449  } else {
+
3450  cudaDeviceSynchronize();
+
3451  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3452  qureg.firstLevelReduction,
+
3453  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3454  cudaDeviceSynchronize();
+ +
3456  }
+
3457  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3458  }
+
3459  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3460 
+
3461  // compute imag component of inner product
+
3462  getRealComp = 0;
+
3463  numValuesToReduce = qureg.numAmpsPerChunk;
+
3464  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3465  firstTime = 1;
+
3466  while (numValuesToReduce > 1) {
+
3467  if (numValuesToReduce < maxReducedPerLevel) {
+
3468  valuesPerCUDABlock = numValuesToReduce;
+
3469  numCUDABlocks = 1;
+
3470  }
+
3471  else {
+
3472  valuesPerCUDABlock = maxReducedPerLevel;
+
3473  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3474  }
+
3475  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3476  if (firstTime) {
+
3477  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3478  getRealComp,
+
3479  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3480  op.deviceOperator.real, op.deviceOperator.imag,
+
3481  op.numQubits, numValuesToReduce,
+
3482  qureg.firstLevelReduction);
+
3483  firstTime = 0;
+
3484  } else {
+
3485  cudaDeviceSynchronize();
+
3486  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3487  qureg.firstLevelReduction,
+
3488  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3489  cudaDeviceSynchronize();
+ +
3491  }
+
3492  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3493  }
+
3494  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3495 
+
3496  // return complex
+
3497  Complex expecVal;
+
3498  expecVal.real = expecReal;
+
3499  expecVal.imag = expecImag;
+
3500  return expecVal;
+
3501 }
+
+

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, DiagonalOp::numQubits, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcExpecDiagonalOp().

@@ -1117,44 +1117,44 @@

if the thread represents a diagonal op, then it computes either a real or imag term of matr_{ii} op_i. Otherwise, it writes a 0 to the reduction array

-

Definition at line 3365 of file QuEST_gpu.cu.

-
3369 {
-
3375  // index will identy one of the 2^Q diagonals to be summed
-
3376  long long int matInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3377  if (matInd >= numTermsToSum) return;
-
3378 
-
3379  long long int diagSpacing = (1LL << numQubits) + 1LL;
-
3380  int isDiag = ((matInd % diagSpacing) == 0);
-
3381 
-
3382  long long int opInd = matInd / diagSpacing;
+

Definition at line 3367 of file QuEST_gpu.cu.

+
3371 {
+
3377  // index will identy one of the 2^Q diagonals to be summed
+
3378  long long int matInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3379  if (matInd >= numTermsToSum) return;
+
3380 
+
3381  long long int diagSpacing = (1LL << numQubits) + 1LL;
+
3382  int isDiag = ((matInd % diagSpacing) == 0);
3383 
-
3384  qreal val = 0;
-
3385  if (isDiag) {
-
3386 
-
3387  qreal matRe = matReal[matInd];
-
3388  qreal matIm = matImag[matInd];
-
3389  qreal opRe = opReal[opInd];
-
3390  qreal opIm = opImag[opInd];
-
3391 
-
3392  // (matRe + matIm i)(opRe + opIm i) =
-
3393  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3394  if (getRealComp)
-
3395  val = matRe * opRe - matIm * opIm;
-
3396  else
-
3397  val = matRe * opIm + matIm * opRe;
-
3398  }
-
3399 
-
3400  // array of each thread's collected sum term, to be summed
-
3401  extern __shared__ qreal tempReductionArray[];
-
3402  tempReductionArray[threadIdx.x] = val;
-
3403  __syncthreads();
-
3404 
-
3405  // every second thread reduces
-
3406  if (threadIdx.x<blockDim.x/2)
-
3407  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3408 }
-
-

References qreal, and reduceBlock().

+
3384  long long int opInd = matInd / diagSpacing;
+
3385 
+
3386  qreal val = 0;
+
3387  if (isDiag) {
+
3388 
+
3389  qreal matRe = matReal[matInd];
+
3390  qreal matIm = matImag[matInd];
+
3391  qreal opRe = opReal[opInd];
+
3392  qreal opIm = opImag[opInd];
+
3393 
+
3394  // (matRe + matIm i)(opRe + opIm i) =
+
3395  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
+
3396  if (getRealComp)
+
3397  val = matRe * opRe - matIm * opIm;
+
3398  else
+
3399  val = matRe * opIm + matIm * opRe;
+
3400  }
+
3401 
+
3402  // array of each thread's collected sum term, to be summed
+
3403  extern __shared__ qreal tempReductionArray[];
+
3404  tempReductionArray[threadIdx.x] = val;
+
3405  __syncthreads();
+
3406 
+
3407  // every second thread reduces
+
3408  if (threadIdx.x<blockDim.x/2)
+
3409  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
3410 }
+
+

References qreal, and reduceBlock().

@@ -1184,60 +1184,60 @@

-

Definition at line 2517 of file QuEST_gpu.cu.

-
2517  {
-
2518 
-
2519  // we're summing the square of every term in the density matrix
-
2520  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
2521  long long int numValuesToReduce = densityDim;
-
2522 
-
2523  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2524  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2525  int firstTime = 1;
-
2526 
-
2527  while (numValuesToReduce > 1) {
-
2528 
-
2529  // need less than one CUDA-BLOCK to reduce
-
2530  if (numValuesToReduce < maxReducedPerLevel) {
-
2531  valuesPerCUDABlock = numValuesToReduce;
-
2532  numCUDABlocks = 1;
-
2533  }
-
2534  // otherwise use only full CUDA-BLOCKS
-
2535  else {
-
2536  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2537  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2538  }
-
2539  // dictates size of reduction array
-
2540  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2541 
-
2542  // spawn threads to sum the probs in each block
-
2543  // store the reduction in the pureState array
-
2544  if (firstTime) {
-
2545  densmatr_calcFidelityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2546  qureg, pureState, densityDim, pureState.firstLevelReduction);
-
2547  firstTime = 0;
-
2548 
-
2549  // sum the block probs
-
2550  } else {
-
2551  cudaDeviceSynchronize();
-
2552  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2553  pureState.firstLevelReduction,
-
2554  pureState.secondLevelReduction, valuesPerCUDABlock);
-
2555  cudaDeviceSynchronize();
-
2556  swapDouble(&(pureState.firstLevelReduction), &(pureState.secondLevelReduction));
-
2557  }
-
2558 
-
2559  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2560  }
-
2561 
-
2562  qreal fidelity;
-
2563  cudaMemcpy(&fidelity, pureState.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2564  return fidelity;
-
2565 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcFidelity().

+

Definition at line 2519 of file QuEST_gpu.cu.

+
2519  {
+
2520 
+
2521  // we're summing the square of every term in the density matrix
+
2522  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
2523  long long int numValuesToReduce = densityDim;
+
2524 
+
2525  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2526  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2527  int firstTime = 1;
+
2528 
+
2529  while (numValuesToReduce > 1) {
+
2530 
+
2531  // need less than one CUDA-BLOCK to reduce
+
2532  if (numValuesToReduce < maxReducedPerLevel) {
+
2533  valuesPerCUDABlock = numValuesToReduce;
+
2534  numCUDABlocks = 1;
+
2535  }
+
2536  // otherwise use only full CUDA-BLOCKS
+
2537  else {
+
2538  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2539  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2540  }
+
2541  // dictates size of reduction array
+
2542  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2543 
+
2544  // spawn threads to sum the probs in each block
+
2545  // store the reduction in the pureState array
+
2546  if (firstTime) {
+
2547  densmatr_calcFidelityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2548  qureg, pureState, densityDim, pureState.firstLevelReduction);
+
2549  firstTime = 0;
+
2550 
+
2551  // sum the block probs
+
2552  } else {
+
2553  cudaDeviceSynchronize();
+
2554  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2555  pureState.firstLevelReduction,
+
2556  pureState.secondLevelReduction, valuesPerCUDABlock);
+
2557  cudaDeviceSynchronize();
+
2558  swapDouble(&(pureState.firstLevelReduction), &(pureState.secondLevelReduction));
+
2559  }
+
2560 
+
2561  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2562  }
+
2563 
+
2564  qreal fidelity;
+
2565  cudaMemcpy(&fidelity, pureState.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2566  return fidelity;
+
2567 }
+
+

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcFidelity().

@@ -1281,46 +1281,46 @@

Definition at line 2479 of file QuEST_gpu.cu.

-
2479  {
-
2480 
-
2481  // figure out which density matrix row to consider
-
2482  long long int col;
-
2483  long long int row = blockIdx.x*blockDim.x + threadIdx.x;
-
2484  if (row >= dim) return;
-
2485 
-
2486  qreal* densReal = dens.deviceStateVec.real;
-
2487  qreal* densImag = dens.deviceStateVec.imag;
-
2488  qreal* vecReal = vec.deviceStateVec.real;
-
2489  qreal* vecImag = vec.deviceStateVec.imag;
-
2490 
-
2491  // compute the row-th element of the product dens*vec
-
2492  qreal prodReal = 0;
-
2493  qreal prodImag = 0;
-
2494  for (col=0LL; col < dim; col++) {
-
2495  qreal densElemReal = densReal[dim*col + row];
-
2496  qreal densElemImag = densImag[dim*col + row];
-
2497 
-
2498  prodReal += densElemReal*vecReal[col] - densElemImag*vecImag[col];
-
2499  prodImag += densElemReal*vecImag[col] + densElemImag*vecReal[col];
-
2500  }
-
2501 
-
2502  // multiply with row-th elem of (vec^*)
-
2503  qreal termReal = prodImag*vecImag[row] + prodReal*vecReal[row];
-
2504 
-
2505  // imag of every term should be zero, because each is a valid fidelity calc of an eigenstate
-
2506  //qreal termImag = prodImag*vecReal[row] - prodReal*vecImag[row];
-
2507 
-
2508  extern __shared__ qreal tempReductionArray[];
-
2509  tempReductionArray[threadIdx.x] = termReal;
-
2510  __syncthreads();
-
2511 
-
2512  // every second thread reduces
-
2513  if (threadIdx.x<blockDim.x/2)
-
2514  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2515 }
-
-

References Qureg::deviceStateVec, qreal, and reduceBlock().

+

Definition at line 2481 of file QuEST_gpu.cu.

+
2481  {
+
2482 
+
2483  // figure out which density matrix row to consider
+
2484  long long int col;
+
2485  long long int row = blockIdx.x*blockDim.x + threadIdx.x;
+
2486  if (row >= dim) return;
+
2487 
+
2488  qreal* densReal = dens.deviceStateVec.real;
+
2489  qreal* densImag = dens.deviceStateVec.imag;
+
2490  qreal* vecReal = vec.deviceStateVec.real;
+
2491  qreal* vecImag = vec.deviceStateVec.imag;
+
2492 
+
2493  // compute the row-th element of the product dens*vec
+
2494  qreal prodReal = 0;
+
2495  qreal prodImag = 0;
+
2496  for (col=0LL; col < dim; col++) {
+
2497  qreal densElemReal = densReal[dim*col + row];
+
2498  qreal densElemImag = densImag[dim*col + row];
+
2499 
+
2500  prodReal += densElemReal*vecReal[col] - densElemImag*vecImag[col];
+
2501  prodImag += densElemReal*vecImag[col] + densElemImag*vecReal[col];
+
2502  }
+
2503 
+
2504  // multiply with row-th elem of (vec^*)
+
2505  qreal termReal = prodImag*vecImag[row] + prodReal*vecReal[row];
+
2506 
+
2507  // imag of every term should be zero, because each is a valid fidelity calc of an eigenstate
+
2508  //qreal termImag = prodImag*vecReal[row] - prodReal*vecImag[row];
+
2509 
+
2510  extern __shared__ qreal tempReductionArray[];
+
2511  tempReductionArray[threadIdx.x] = termReal;
+
2512  __syncthreads();
+
2513 
+
2514  // every second thread reduces
+
2515  if (threadIdx.x<blockDim.x/2)
+
2516  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2517 }
+
+

References Qureg::deviceStateVec, qreal, and reduceBlock().

@@ -1350,62 +1350,62 @@

-

Definition at line 2591 of file QuEST_gpu.cu.

-
2591  {
-
2592 
-
2593  // we're summing the square of every term in (a-b)
-
2594  long long int numValuesToReduce = a.numAmpsPerChunk;
-
2595 
-
2596  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2597  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2598  int firstTime = 1;
-
2599 
-
2600  while (numValuesToReduce > 1) {
-
2601 
-
2602  // need less than one CUDA-BLOCK to reduce
-
2603  if (numValuesToReduce < maxReducedPerLevel) {
-
2604  valuesPerCUDABlock = numValuesToReduce;
-
2605  numCUDABlocks = 1;
-
2606  }
-
2607  // otherwise use only full CUDA-BLOCKS
-
2608  else {
-
2609  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2610  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2611  }
-
2612  // dictates size of reduction array
-
2613  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2614 
-
2615  // spawn threads to sum the probs in each block (store reduction temp values in a's reduction array)
-
2616  if (firstTime) {
-
2617  densmatr_calcHilbertSchmidtDistanceSquaredKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2618  a.deviceStateVec.real, a.deviceStateVec.imag,
-
2619  b.deviceStateVec.real, b.deviceStateVec.imag,
-
2620  numValuesToReduce, a.firstLevelReduction);
-
2621  firstTime = 0;
-
2622 
-
2623  // sum the block probs
-
2624  } else {
-
2625  cudaDeviceSynchronize();
-
2626  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2628  a.secondLevelReduction, valuesPerCUDABlock);
-
2629  cudaDeviceSynchronize();
- -
2631  }
-
2632 
-
2633  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2634  }
-
2635 
-
2636  qreal trace;
-
2637  cudaMemcpy(&trace, a.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2638 
-
2639  qreal sqrtTrace = sqrt(trace);
-
2640  return sqrtTrace;
-
2641 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcHilbertSchmidtDistance().

+

Definition at line 2593 of file QuEST_gpu.cu.

+
2593  {
+
2594 
+
2595  // we're summing the square of every term in (a-b)
+
2596  long long int numValuesToReduce = a.numAmpsPerChunk;
+
2597 
+
2598  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2599  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2600  int firstTime = 1;
+
2601 
+
2602  while (numValuesToReduce > 1) {
+
2603 
+
2604  // need less than one CUDA-BLOCK to reduce
+
2605  if (numValuesToReduce < maxReducedPerLevel) {
+
2606  valuesPerCUDABlock = numValuesToReduce;
+
2607  numCUDABlocks = 1;
+
2608  }
+
2609  // otherwise use only full CUDA-BLOCKS
+
2610  else {
+
2611  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2612  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2613  }
+
2614  // dictates size of reduction array
+
2615  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2616 
+
2617  // spawn threads to sum the probs in each block (store reduction temp values in a's reduction array)
+
2618  if (firstTime) {
+
2619  densmatr_calcHilbertSchmidtDistanceSquaredKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2620  a.deviceStateVec.real, a.deviceStateVec.imag,
+
2621  b.deviceStateVec.real, b.deviceStateVec.imag,
+
2622  numValuesToReduce, a.firstLevelReduction);
+
2623  firstTime = 0;
+
2624 
+
2625  // sum the block probs
+
2626  } else {
+
2627  cudaDeviceSynchronize();
+
2628  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+ +
2630  a.secondLevelReduction, valuesPerCUDABlock);
+
2631  cudaDeviceSynchronize();
+ +
2633  }
+
2634 
+
2635  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2636  }
+
2637 
+
2638  qreal trace;
+
2639  cudaMemcpy(&trace, a.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2640 
+
2641  qreal sqrtTrace = sqrt(trace);
+
2642  return sqrtTrace;
+
2643 }
+
+

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcHilbertSchmidtDistance().

@@ -1459,28 +1459,28 @@

-

Definition at line 2567 of file QuEST_gpu.cu.

-
2570  {
-
2571  // figure out which density matrix term this thread is assigned
-
2572  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2573  if (index >= numAmpsToSum) return;
-
2574 
-
2575  // compute this thread's sum term
-
2576  qreal difRe = aRe[index] - bRe[index];
-
2577  qreal difIm = aIm[index] - bIm[index];
-
2578  qreal term = difRe*difRe + difIm*difIm;
-
2579 
-
2580  // array of each thread's collected term, to be summed
-
2581  extern __shared__ qreal tempReductionArray[];
-
2582  tempReductionArray[threadIdx.x] = term;
-
2583  __syncthreads();
-
2584 
-
2585  // every second thread reduces
-
2586  if (threadIdx.x<blockDim.x/2)
-
2587  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2588 }
+

Definition at line 2569 of file QuEST_gpu.cu.

+
2572  {
+
2573  // figure out which density matrix term this thread is assigned
+
2574  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2575  if (index >= numAmpsToSum) return;
+
2576 
+
2577  // compute this thread's sum term
+
2578  qreal difRe = aRe[index] - bRe[index];
+
2579  qreal difIm = aIm[index] - bIm[index];
+
2580  qreal term = difRe*difRe + difIm*difIm;
+
2581 
+
2582  // array of each thread's collected term, to be summed
+
2583  extern __shared__ qreal tempReductionArray[];
+
2584  tempReductionArray[threadIdx.x] = term;
+
2585  __syncthreads();
+
2586 
+
2587  // every second thread reduces
+
2588  if (threadIdx.x<blockDim.x/2)
+
2589  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2590 }
-

References qreal, and reduceBlock().

+

References qreal, and reduceBlock().

@@ -1510,59 +1510,59 @@

-

Definition at line 2311 of file QuEST_gpu.cu.

-
2311  {
-
2312 
-
2313  // we're summing the square of every term in the density matrix
-
2314  long long int numValuesToReduce = a.numAmpsTotal;
-
2315 
-
2316  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2317  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2318  int firstTime = 1;
-
2319 
-
2320  while (numValuesToReduce > 1) {
-
2321 
-
2322  // need less than one CUDA-BLOCK to reduce
-
2323  if (numValuesToReduce < maxReducedPerLevel) {
-
2324  valuesPerCUDABlock = numValuesToReduce;
-
2325  numCUDABlocks = 1;
-
2326  }
-
2327  // otherwise use only full CUDA-BLOCKS
-
2328  else {
-
2329  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2330  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2331  }
-
2332  // dictates size of reduction array
-
2333  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2334 
-
2335  // spawn threads to sum the terms in each block
-
2336  // arbitrarily store the reduction in the b qureg's array
-
2337  if (firstTime) {
-
2338  densmatr_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2339  a, b, a.numAmpsTotal, b.firstLevelReduction);
-
2340  firstTime = 0;
-
2341  }
-
2342  // sum the block terms
-
2343  else {
-
2344  cudaDeviceSynchronize();
-
2345  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2347  b.secondLevelReduction, valuesPerCUDABlock);
-
2348  cudaDeviceSynchronize();
- -
2350  }
-
2351 
-
2352  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2353  }
-
2354 
-
2355  qreal innerprod;
-
2356  cudaMemcpy(&innerprod, b.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2357  return innerprod;
-
2358 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcDensityInnerProduct().

+

Definition at line 2313 of file QuEST_gpu.cu.

+
2313  {
+
2314 
+
2315  // we're summing the square of every term in the density matrix
+
2316  long long int numValuesToReduce = a.numAmpsTotal;
+
2317 
+
2318  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2319  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2320  int firstTime = 1;
+
2321 
+
2322  while (numValuesToReduce > 1) {
+
2323 
+
2324  // need less than one CUDA-BLOCK to reduce
+
2325  if (numValuesToReduce < maxReducedPerLevel) {
+
2326  valuesPerCUDABlock = numValuesToReduce;
+
2327  numCUDABlocks = 1;
+
2328  }
+
2329  // otherwise use only full CUDA-BLOCKS
+
2330  else {
+
2331  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2332  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2333  }
+
2334  // dictates size of reduction array
+
2335  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2336 
+
2337  // spawn threads to sum the terms in each block
+
2338  // arbitrarily store the reduction in the b qureg's array
+
2339  if (firstTime) {
+
2340  densmatr_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2341  a, b, a.numAmpsTotal, b.firstLevelReduction);
+
2342  firstTime = 0;
+
2343  }
+
2344  // sum the block terms
+
2345  else {
+
2346  cudaDeviceSynchronize();
+
2347  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+ +
2349  b.secondLevelReduction, valuesPerCUDABlock);
+
2350  cudaDeviceSynchronize();
+ +
2352  }
+
2353 
+
2354  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2355  }
+
2356 
+
2357  qreal innerprod;
+
2358  cudaMemcpy(&innerprod, b.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2359  return innerprod;
+
2360 }
+
+

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcDensityInnerProduct().

@@ -1606,27 +1606,27 @@

Definition at line 2290 of file QuEST_gpu.cu.

-
2292  {
-
2293  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2294  if (index >= numTermsToSum) return;
-
2295 
-
2296  // Re{ conj(a) b } = Re{ (aRe - i aIm)(bRe + i bIm) } = aRe bRe + aIm bIm
-
2297  qreal prod = (
-
2298  a.deviceStateVec.real[index]*b.deviceStateVec.real[index]
-
2299  + a.deviceStateVec.imag[index]*b.deviceStateVec.imag[index]);
-
2300 
-
2301  // array of each thread's collected sum term, to be summed
-
2302  extern __shared__ qreal tempReductionArray[];
-
2303  tempReductionArray[threadIdx.x] = prod;
-
2304  __syncthreads();
-
2305 
-
2306  // every second thread reduces
-
2307  if (threadIdx.x<blockDim.x/2)
-
2308  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2309 }
-
-

References Qureg::deviceStateVec, qreal, and reduceBlock().

+

Definition at line 2292 of file QuEST_gpu.cu.

+
2294  {
+
2295  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2296  if (index >= numTermsToSum) return;
+
2297 
+
2298  // Re{ conj(a) b } = Re{ (aRe - i aIm)(bRe + i bIm) } = aRe bRe + aIm bIm
+
2299  qreal prod = (
+
2300  a.deviceStateVec.real[index]*b.deviceStateVec.real[index]
+
2301  + a.deviceStateVec.imag[index]*b.deviceStateVec.imag[index]);
+
2302 
+
2303  // array of each thread's collected sum term, to be summed
+
2304  extern __shared__ qreal tempReductionArray[];
+
2305  tempReductionArray[threadIdx.x] = prod;
+
2306  __syncthreads();
+
2307 
+
2308  // every second thread reduces
+
2309  if (threadIdx.x<blockDim.x/2)
+
2310  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2311 }
+
+

References Qureg::deviceStateVec, qreal, and reduceBlock().

@@ -1668,42 +1668,42 @@

-

Definition at line 2257 of file QuEST_gpu.cu.

-
2257  {
-
2258 
-
2259  // copy qubits to GPU memory
-
2260  int* d_qubits;
-
2261  size_t mem_qubits = numQubits * sizeof *d_qubits;
-
2262  cudaMalloc(&d_qubits, mem_qubits);
-
2263  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
2264 
-
2265  // create global array, with per-block subarrays
-
2266  int numThreadsPerBlock = 128;
-
2267  int numDiags = (1LL << qureg.numQubitsRepresented);
-
2268  int numBlocks = ceil(numDiags / (qreal) numThreadsPerBlock);
-
2269 
-
2270  // create global GPU array for outcomeProbs
-
2271  qreal* d_outcomeProbs;
-
2272  long long int numOutcomes = (1LL << numQubits);
-
2273  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
-
2274  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
-
2275  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
-
2276 
-
2277  // populate per-block subarrays
-
2278  densmatr_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
-
2279  d_outcomeProbs, qureg, d_qubits, numQubits);
-
2280 
-
2281  // copy outcomeProbs from GPU memory
-
2282  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
-
2283 
-
2284  // free GPU memory
-
2285  cudaFree(d_qubits);
-
2286  cudaFree(d_outcomeProbs);
-
2287 }
+

Definition at line 2259 of file QuEST_gpu.cu.

+
2259  {
+
2260 
+
2261  // copy qubits to GPU memory
+
2262  int* d_qubits;
+
2263  size_t mem_qubits = numQubits * sizeof *d_qubits;
+
2264  cudaMalloc(&d_qubits, mem_qubits);
+
2265  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
2266 
+
2267  // create global array, with per-block subarrays
+
2268  int numThreadsPerBlock = 128;
+
2269  int numDiags = (1LL << qureg.numQubitsRepresented);
+
2270  int numBlocks = ceil(numDiags / (qreal) numThreadsPerBlock);
+
2271 
+
2272  // create global GPU array for outcomeProbs
+
2273  qreal* d_outcomeProbs;
+
2274  long long int numOutcomes = (1LL << numQubits);
+
2275  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
+
2276  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
+
2277  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
+
2278 
+
2279  // populate per-block subarrays
+
2280  densmatr_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
+
2281  d_outcomeProbs, qureg, d_qubits, numQubits);
+
2282 
+
2283  // copy outcomeProbs from GPU memory
+
2284  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
+
2285 
+
2286  // free GPU memory
+
2287  cudaFree(d_qubits);
+
2288  cudaFree(d_outcomeProbs);
+
2289 }

References Qureg::numQubitsRepresented, and qreal.

-

Referenced by calcProbOfAllOutcomes().

+

Referenced by calcProbOfAllOutcomes().

@@ -1745,25 +1745,25 @@

-

Definition at line 2236 of file QuEST_gpu.cu.

-
2238  {
-
2239  // each thread handles one diagonal amplitude
-
2240  long long int diagInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2241  long long int numDiags = (1LL << qureg.numQubitsRepresented);
-
2242  if (diagInd >= numDiags) return;
-
2243 
-
2244  long long int flatInd = (1 + numDiags)*diagInd;
-
2245  qreal prob = qureg.deviceStateVec.real[flatInd]; // im[flatInd] assumed ~ 0
-
2246 
-
2247  // each diagonal amplitude contributes to one outcome
-
2248  long long int outcomeInd = 0;
-
2249  for (int q=0; q<numQubits; q++)
-
2250  outcomeInd += extractBit(qubits[q], diagInd) * (1LL << q);
-
2251 
-
2252  // each thread atomically writes directly to the global output.
-
2253  // this beat block-heirarchal atomic reductions in both global and shared memory!
-
2254  atomicAdd(&outcomeProbs[outcomeInd], prob);
-
2255 }
+

Definition at line 2238 of file QuEST_gpu.cu.

+
2240  {
+
2241  // each thread handles one diagonal amplitude
+
2242  long long int diagInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2243  long long int numDiags = (1LL << qureg.numQubitsRepresented);
+
2244  if (diagInd >= numDiags) return;
+
2245 
+
2246  long long int flatInd = (1 + numDiags)*diagInd;
+
2247  qreal prob = qureg.deviceStateVec.real[flatInd]; // im[flatInd] assumed ~ 0
+
2248 
+
2249  // each diagonal amplitude contributes to one outcome
+
2250  long long int outcomeInd = 0;
+
2251  for (int q=0; q<numQubits; q++)
+
2252  outcomeInd += extractBit(qubits[q], diagInd) * (1LL << q);
+
2253 
+
2254  // each thread atomically writes directly to the global output.
+
2255  // this beat block-heirarchal atomic reductions in both global and shared memory!
+
2256  atomicAdd(&outcomeProbs[outcomeInd], prob);
+
2257 }

References Qureg::deviceStateVec, extractBit(), Qureg::numQubitsRepresented, and qreal.

@@ -1801,17 +1801,17 @@

-

Definition at line 2156 of file QuEST_gpu.cu.

-
2157 {
-
2158  qreal outcomeProb = densmatr_findProbabilityOfZero(qureg, measureQubit);
-
2159  if (outcome==1)
-
2160  outcomeProb = 1.0 - outcomeProb;
-
2161  return outcomeProb;
-
2162 }
+

Definition at line 2158 of file QuEST_gpu.cu.

+
2159 {
+
2160  qreal outcomeProb = densmatr_findProbabilityOfZero(qureg, measureQubit);
+
2161  if (outcome==1)
+
2162  outcomeProb = 1.0 - outcomeProb;
+
2163  return outcomeProb;
+
2164 }
-

References densmatr_findProbabilityOfZero(), and qreal.

+

References densmatr_findProbabilityOfZero(), and qreal.

-

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

+

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

@@ -1833,59 +1833,59 @@

Definition at line 2662 of file QuEST_gpu.cu.

-
2662  {
-
2663 
-
2664  // we're summing the square of every term in the density matrix
-
2665  long long int numValuesToReduce = qureg.numAmpsPerChunk;
-
2666 
-
2667  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2668  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2669  int firstTime = 1;
-
2670 
-
2671  while (numValuesToReduce > 1) {
-
2672 
-
2673  // need less than one CUDA-BLOCK to reduce
-
2674  if (numValuesToReduce < maxReducedPerLevel) {
-
2675  valuesPerCUDABlock = numValuesToReduce;
-
2676  numCUDABlocks = 1;
-
2677  }
-
2678  // otherwise use only full CUDA-BLOCKS
-
2679  else {
-
2680  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2681  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2682  }
-
2683  // dictates size of reduction array
-
2684  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2685 
-
2686  // spawn threads to sum the probs in each block
-
2687  if (firstTime) {
-
2688  densmatr_calcPurityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2689  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
2690  numValuesToReduce, qureg.firstLevelReduction);
-
2691  firstTime = 0;
-
2692 
-
2693  // sum the block probs
-
2694  } else {
-
2695  cudaDeviceSynchronize();
-
2696  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2697  qureg.firstLevelReduction,
-
2698  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2699  cudaDeviceSynchronize();
- -
2701  }
-
2702 
-
2703  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2704  }
-
2705 
-
2706  qreal traceDensSquared;
-
2707  cudaMemcpy(&traceDensSquared, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2708  return traceDensSquared;
-
2709 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcPurity().

+

Definition at line 2664 of file QuEST_gpu.cu.

+
2664  {
+
2665 
+
2666  // we're summing the square of every term in the density matrix
+
2667  long long int numValuesToReduce = qureg.numAmpsPerChunk;
+
2668 
+
2669  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2670  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2671  int firstTime = 1;
+
2672 
+
2673  while (numValuesToReduce > 1) {
+
2674 
+
2675  // need less than one CUDA-BLOCK to reduce
+
2676  if (numValuesToReduce < maxReducedPerLevel) {
+
2677  valuesPerCUDABlock = numValuesToReduce;
+
2678  numCUDABlocks = 1;
+
2679  }
+
2680  // otherwise use only full CUDA-BLOCKS
+
2681  else {
+
2682  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2683  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2684  }
+
2685  // dictates size of reduction array
+
2686  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2687 
+
2688  // spawn threads to sum the probs in each block
+
2689  if (firstTime) {
+
2690  densmatr_calcPurityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2691  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
2692  numValuesToReduce, qureg.firstLevelReduction);
+
2693  firstTime = 0;
+
2694 
+
2695  // sum the block probs
+
2696  } else {
+
2697  cudaDeviceSynchronize();
+
2698  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2699  qureg.firstLevelReduction,
+
2700  qureg.secondLevelReduction, valuesPerCUDABlock);
+
2701  cudaDeviceSynchronize();
+ +
2703  }
+
2704 
+
2705  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2706  }
+
2707 
+
2708  qreal traceDensSquared;
+
2709  cudaMemcpy(&traceDensSquared, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2710  return traceDensSquared;
+
2711 }
+
+

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcPurity().

@@ -1927,26 +1927,26 @@

-

Definition at line 2643 of file QuEST_gpu.cu.

-
2643  {
-
2644 
-
2645  // figure out which density matrix term this thread is assigned
-
2646  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2647  if (index >= numAmpsToSum) return;
-
2648 
-
2649  qreal term = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+

Definition at line 2645 of file QuEST_gpu.cu.

+
2645  {
+
2646 
+
2647  // figure out which density matrix term this thread is assigned
+
2648  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2649  if (index >= numAmpsToSum) return;
2650 
-
2651  // array of each thread's collected probability, to be summed
-
2652  extern __shared__ qreal tempReductionArray[];
-
2653  tempReductionArray[threadIdx.x] = term;
-
2654  __syncthreads();
-
2655 
-
2656  // every second thread reduces
-
2657  if (threadIdx.x<blockDim.x/2)
-
2658  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2659 }
+
2651  qreal term = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+
2652 
+
2653  // array of each thread's collected probability, to be summed
+
2654  extern __shared__ qreal tempReductionArray[];
+
2655  tempReductionArray[threadIdx.x] = term;
+
2656  __syncthreads();
+
2657 
+
2658  // every second thread reduces
+
2659  if (threadIdx.x<blockDim.x/2)
+
2660  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2661 }
-

References qreal, and reduceBlock().

+

References qreal, and reduceBlock().

@@ -1966,33 +1966,33 @@

-

Definition at line 1630 of file QuEST_gpu.cu.

-
1630  {
-
1631 
-
1632  // computes the trace using Kahan summation
-
1633  qreal pTotal=0;
-
1634  qreal y, t, c;
-
1635  c = 0;
-
1636 
-
1637  long long int numCols = 1LL << qureg.numQubitsRepresented;
-
1638  long long diagIndex;
-
1639 
-
1640  copyStateFromGPU(qureg);
+

Definition at line 1632 of file QuEST_gpu.cu.

+
1632  {
+
1633 
+
1634  // computes the trace using Kahan summation
+
1635  qreal pTotal=0;
+
1636  qreal y, t, c;
+
1637  c = 0;
+
1638 
+
1639  long long int numCols = 1LL << qureg.numQubitsRepresented;
+
1640  long long diagIndex;
1641 
-
1642  for (int col=0; col< numCols; col++) {
-
1643  diagIndex = col*(numCols + 1);
-
1644  y = qureg.stateVec.real[diagIndex] - c;
-
1645  t = pTotal + y;
-
1646  c = ( t - pTotal ) - y; // brackets are important
-
1647  pTotal = t;
-
1648  }
-
1649 
-
1650  return pTotal;
-
1651 }
+
1642  copyStateFromGPU(qureg);
+
1643 
+
1644  for (int col=0; col< numCols; col++) {
+
1645  diagIndex = col*(numCols + 1);
+
1646  y = qureg.stateVec.real[diagIndex] - c;
+
1647  t = pTotal + y;
+
1648  c = ( t - pTotal ) - y; // brackets are important
+
1649  pTotal = t;
+
1650  }
+
1651 
+
1652  return pTotal;
+
1653 }
-

References copyStateFromGPU(), Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

+

References copyStateFromGPU(), Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

+

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

@@ -2037,39 +2037,39 @@

Definition at line 2803 of file QuEST_gpu.cu.

-
2803  {
-
2804 
-
2805  int rowQubit = measureQubit + qureg.numQubitsRepresented;
+

Definition at line 2805 of file QuEST_gpu.cu.

+
2805  {
2806 
-
2807  int colBit = 1LL << measureQubit;
-
2808  int rowBit = 1LL << rowQubit;
-
2809 
-
2810  long long int numBasesToVisit = qureg.numAmpsPerChunk/4;
-
2811  long long int part1 = colBit -1;
-
2812  long long int part2 = (rowBit >> 1) - colBit;
-
2813  long long int part3 = numBasesToVisit - (rowBit >> 1);
-
2814 
-
2815  long long int desired, undesired;
-
2816  if (outcome == 0) {
-
2817  desired = 0;
-
2818  undesired = colBit | rowBit;
-
2819  } else {
-
2820  desired = colBit | rowBit;
-
2821  undesired = 0;
-
2822  }
-
2823 
-
2824  int threadsPerCUDABlock, CUDABlocks;
-
2825  threadsPerCUDABlock = 128;
-
2826  CUDABlocks = ceil(numBasesToVisit / (qreal) threadsPerCUDABlock);
-
2827  densmatr_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2828  outcomeProb, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBasesToVisit,
-
2829  part1, part2, part3, rowBit, colBit, desired, undesired);
-
2830 }
+
2807  int rowQubit = measureQubit + qureg.numQubitsRepresented;
+
2808 
+
2809  int colBit = 1LL << measureQubit;
+
2810  int rowBit = 1LL << rowQubit;
+
2811 
+
2812  long long int numBasesToVisit = qureg.numAmpsPerChunk/4;
+
2813  long long int part1 = colBit -1;
+
2814  long long int part2 = (rowBit >> 1) - colBit;
+
2815  long long int part3 = numBasesToVisit - (rowBit >> 1);
+
2816 
+
2817  long long int desired, undesired;
+
2818  if (outcome == 0) {
+
2819  desired = 0;
+
2820  undesired = colBit | rowBit;
+
2821  } else {
+
2822  desired = colBit | rowBit;
+
2823  undesired = 0;
+
2824  }
+
2825 
+
2826  int threadsPerCUDABlock, CUDABlocks;
+
2827  threadsPerCUDABlock = 128;
+
2828  CUDABlocks = ceil(numBasesToVisit / (qreal) threadsPerCUDABlock);
+
2829  densmatr_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2830  outcomeProb, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBasesToVisit,
+
2831  part1, part2, part3, rowBit, colBit, desired, undesired);
+
2832 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by collapseToOutcome(), and densmatr_measureWithStats().

+

Referenced by applyProjector(), collapseToOutcome(), and densmatr_measureWithStats().

@@ -2155,27 +2155,27 @@

Definition at line 2777 of file QuEST_gpu.cu.

-
2781 {
-
2782  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2783  if (scanInd >= numBasesToVisit) return;
-
2784 
-
2785  long long int base = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+

Definition at line 2779 of file QuEST_gpu.cu.

+
2783 {
+
2784  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2785  if (scanInd >= numBasesToVisit) return;
2786 
-
2787  // renormalise desired outcome
-
2788  vecReal[base + desired] /= outcomeProb;
-
2789  vecImag[base + desired] /= outcomeProb;
-
2790 
-
2791  // kill undesired outcome
-
2792  vecReal[base + undesired] = 0;
-
2793  vecImag[base + undesired] = 0;
-
2794 
-
2795  // kill |..0..><..1..| states
-
2796  vecReal[base + colBit] = 0;
-
2797  vecImag[base + colBit] = 0;
-
2798  vecReal[base + rowBit] = 0;
-
2799  vecImag[base + rowBit] = 0;
-
2800 }
+
2787  long long int base = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2788 
+
2789  // renormalise desired outcome
+
2790  vecReal[base + desired] /= outcomeProb;
+
2791  vecImag[base + desired] /= outcomeProb;
+
2792 
+
2793  // kill undesired outcome
+
2794  vecReal[base + undesired] = 0;
+
2795  vecImag[base + undesired] = 0;
+
2796 
+
2797  // kill |..0..><..1..| states
+
2798  vecReal[base + colBit] = 0;
+
2799  vecImag[base + colBit] = 0;
+
2800  vecReal[base + rowBit] = 0;
+
2801  vecImag[base + rowBit] = 0;
+
2802 }
@@ -2205,57 +2205,57 @@

-

Definition at line 2062 of file QuEST_gpu.cu.

-
2063 {
-
2064  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
2065  long long int numValuesToReduce = densityDim >> 1; // half of the diagonal has measureQubit=0
-
2066 
-
2067  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2068  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2069  int firstTime = 1;
-
2070 
-
2071  while (numValuesToReduce > 1) {
-
2072 
-
2073  // need less than one CUDA-BLOCK to reduce
-
2074  if (numValuesToReduce < maxReducedPerLevel) {
-
2075  valuesPerCUDABlock = numValuesToReduce;
-
2076  numCUDABlocks = 1;
-
2077  }
-
2078  // otherwise use only full CUDA-BLOCKS
-
2079  else {
-
2080  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2081  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2082  }
-
2083 
-
2084  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+

Definition at line 2064 of file QuEST_gpu.cu.

+
2065 {
+
2066  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
2067  long long int numValuesToReduce = densityDim >> 1; // half of the diagonal has measureQubit=0
+
2068 
+
2069  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2070  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2071  int firstTime = 1;
+
2072 
+
2073  while (numValuesToReduce > 1) {
+
2074 
+
2075  // need less than one CUDA-BLOCK to reduce
+
2076  if (numValuesToReduce < maxReducedPerLevel) {
+
2077  valuesPerCUDABlock = numValuesToReduce;
+
2078  numCUDABlocks = 1;
+
2079  }
+
2080  // otherwise use only full CUDA-BLOCKS
+
2081  else {
+
2082  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2083  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2084  }
2085 
-
2086  // spawn threads to sum the probs in each block
-
2087  if (firstTime) {
-
2088  densmatr_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2089  qureg, measureQubit, qureg.firstLevelReduction);
-
2090  firstTime = 0;
-
2091 
-
2092  // sum the block probs
-
2093  } else {
-
2094  cudaDeviceSynchronize();
-
2095  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2096  qureg.firstLevelReduction,
-
2097  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2098  cudaDeviceSynchronize();
- -
2100  }
-
2101 
-
2102  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2103  }
-
2104 
-
2105  qreal zeroProb;
-
2106  cudaMemcpy(&zeroProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2107  return zeroProb;
-
2108 }
-
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by densmatr_calcProbOfOutcome().

+
2086  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2087 
+
2088  // spawn threads to sum the probs in each block
+
2089  if (firstTime) {
+
2090  densmatr_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2091  qureg, measureQubit, qureg.firstLevelReduction);
+
2092  firstTime = 0;
+
2093 
+
2094  // sum the block probs
+
2095  } else {
+
2096  cudaDeviceSynchronize();
+
2097  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2098  qureg.firstLevelReduction,
+
2099  qureg.secondLevelReduction, valuesPerCUDABlock);
+
2100  cudaDeviceSynchronize();
+ +
2102  }
+
2103 
+
2104  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2105  }
+
2106 
+
2107  qreal zeroProb;
+
2108  cudaMemcpy(&zeroProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2109  return zeroProb;
+
2110 }
+
+

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by densmatr_calcProbOfOutcome().

@@ -2291,44 +2291,44 @@

-

Definition at line 1958 of file QuEST_gpu.cu.

-
1960  {
-
1961  // run by each thread
-
1962  // use of block here refers to contiguous amplitudes where measureQubit = 0,
-
1963  // (then =1) and NOT the CUDA block, which is the partitioning of CUDA threads
-
1964 
-
1965  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1966  long long int numTasks = densityDim >> 1;
-
1967  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1968  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1969 
-
1970  long long int thisBlock; // which block this thread is processing
-
1971  long long int thisTask; // which part of the block this thread is processing
-
1972  long long int basisIndex; // index of this thread's computational basis state
-
1973  long long int densityIndex; // " " index of |basis><basis| in the flat density matrix
-
1974 
-
1975  // array of each thread's collected probability, to be summed
-
1976  extern __shared__ qreal tempReductionArray[];
-
1977 
-
1978  // figure out which density matrix prob that this thread is assigned
-
1979  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1980  if (thisTask>=numTasks) return;
-
1981  thisBlock = thisTask / sizeHalfBlock;
-
1982  basisIndex = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1983  densityIndex = (densityDim + 1) * basisIndex;
-
1984 
-
1985  // record the probability in the CUDA-BLOCK-wide array
-
1986  qreal prob = qureg.deviceStateVec.real[densityIndex]; // im[densityIndex] assumed ~ 0
-
1987  tempReductionArray[threadIdx.x] = prob;
-
1988 
-
1989  // sum the probs collected by this CUDA-BLOCK's threads into a per-CUDA-BLOCK array
-
1990  __syncthreads();
-
1991  if (threadIdx.x<blockDim.x/2){
-
1992  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
1993  }
-
1994 }
+

Definition at line 1960 of file QuEST_gpu.cu.

+
1962  {
+
1963  // run by each thread
+
1964  // use of block here refers to contiguous amplitudes where measureQubit = 0,
+
1965  // (then =1) and NOT the CUDA block, which is the partitioning of CUDA threads
+
1966 
+
1967  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
1968  long long int numTasks = densityDim >> 1;
+
1969  long long int sizeHalfBlock = 1LL << (measureQubit);
+
1970  long long int sizeBlock = 2LL * sizeHalfBlock;
+
1971 
+
1972  long long int thisBlock; // which block this thread is processing
+
1973  long long int thisTask; // which part of the block this thread is processing
+
1974  long long int basisIndex; // index of this thread's computational basis state
+
1975  long long int densityIndex; // " " index of |basis><basis| in the flat density matrix
+
1976 
+
1977  // array of each thread's collected probability, to be summed
+
1978  extern __shared__ qreal tempReductionArray[];
+
1979 
+
1980  // figure out which density matrix prob that this thread is assigned
+
1981  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1982  if (thisTask>=numTasks) return;
+
1983  thisBlock = thisTask / sizeHalfBlock;
+
1984  basisIndex = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1985  densityIndex = (densityDim + 1) * basisIndex;
+
1986 
+
1987  // record the probability in the CUDA-BLOCK-wide array
+
1988  qreal prob = qureg.deviceStateVec.real[densityIndex]; // im[densityIndex] assumed ~ 0
+
1989  tempReductionArray[threadIdx.x] = prob;
+
1990 
+
1991  // sum the probs collected by this CUDA-BLOCK's threads into a per-CUDA-BLOCK array
+
1992  __syncthreads();
+
1993  if (threadIdx.x<blockDim.x/2){
+
1994  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
1995  }
+
1996 }
-

References Qureg::deviceStateVec, Qureg::numQubitsRepresented, qreal, and reduceBlock().

+

References Qureg::deviceStateVec, Qureg::numQubitsRepresented, qreal, and reduceBlock().

@@ -2662,37 +2662,37 @@

-

Definition at line 3046 of file QuEST_gpu.cu.

-
3046  {
-
3047 
-
3048  if (damping == 0)
-
3049  return;
-
3050 
-
3051  qreal dephase = sqrt(1-damping);
-
3052  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
3053 
-
3054  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
3055  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
3056 
-
3057  long long int colBit = 1LL << targetQubit;
-
3058  long long int rowBit = 1LL << rowQubit;
-
3059  long long int bothBits = colBit | rowBit;
-
3060 
-
3061  long long int part1 = colBit - 1;
-
3062  long long int part2 = (rowBit >> 1) - colBit;
-
3063  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
3064 
-
3065  int threadsPerCUDABlock, CUDABlocks;
-
3066  threadsPerCUDABlock = 128;
-
3067  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3068  densmatr_mixDampingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3069  damping, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
3070  part1, part2, part3, bothBits);
-
3071 }
+

Definition at line 3048 of file QuEST_gpu.cu.

+
3048  {
+
3049 
+
3050  if (damping == 0)
+
3051  return;
+
3052 
+
3053  qreal dephase = sqrt(1-damping);
+
3054  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
+
3055 
+
3056  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
3057  int rowQubit = targetQubit + qureg.numQubitsRepresented;
+
3058 
+
3059  long long int colBit = 1LL << targetQubit;
+
3060  long long int rowBit = 1LL << rowQubit;
+
3061  long long int bothBits = colBit | rowBit;
+
3062 
+
3063  long long int part1 = colBit - 1;
+
3064  long long int part2 = (rowBit >> 1) - colBit;
+
3065  long long int part3 = numAmpsToVisit - (rowBit >> 1);
+
3066 
+
3067  int threadsPerCUDABlock, CUDABlocks;
+
3068  threadsPerCUDABlock = 128;
+
3069  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3070  densmatr_mixDampingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3071  damping, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
3072  part1, part2, part3, bothBits);
+
3073 }
-

References densmatr_oneQubitDegradeOffDiagonal(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+

References densmatr_oneQubitDegradeOffDiagonal(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by mixDamping().

+

Referenced by mixDamping().

@@ -2760,23 +2760,23 @@

Definition at line 2999 of file QuEST_gpu.cu.

-
3003 {
-
3004  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3005  if (scanInd >= numAmpsToVisit) return;
-
3006 
-
3007  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
3008  long long int targetInd = baseInd + bothBits;
-
3009 
-
3010  qreal realAvDepol = damping * ( vecReal[targetInd]);
-
3011  qreal imagAvDepol = damping * ( vecImag[targetInd]);
-
3012 
-
3013  vecReal[targetInd] *= 1 - damping;
-
3014  vecImag[targetInd] *= 1 - damping;
-
3015 
-
3016  vecReal[baseInd] += realAvDepol;
-
3017  vecImag[baseInd] += imagAvDepol;
-
3018 }
+

Definition at line 3001 of file QuEST_gpu.cu.

+
3005 {
+
3006  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3007  if (scanInd >= numAmpsToVisit) return;
+
3008 
+
3009  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
3010  long long int targetInd = baseInd + bothBits;
+
3011 
+
3012  qreal realAvDepol = damping * ( vecReal[targetInd]);
+
3013  qreal imagAvDepol = damping * ( vecImag[targetInd]);
+
3014 
+
3015  vecReal[targetInd] *= 1 - damping;
+
3016  vecImag[targetInd] *= 1 - damping;
+
3017 
+
3018  vecReal[baseInd] += realAvDepol;
+
3019  vecImag[baseInd] += imagAvDepol;
+
3020 }

References qreal.

@@ -2814,22 +2814,22 @@

-

Definition at line 2844 of file QuEST_gpu.cu.

-
2844  {
-
2845 
-
2846  long long int numAmpsToVisit = combineQureg.numAmpsPerChunk;
+

Definition at line 2846 of file QuEST_gpu.cu.

+
2846  {
2847 
-
2848  int threadsPerCUDABlock, CUDABlocks;
-
2849  threadsPerCUDABlock = 128;
-
2850  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2851  densmatr_mixDensityMatrixKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2852  combineQureg, otherProb, otherQureg, numAmpsToVisit
-
2853  );
-
2854 }
+
2848  long long int numAmpsToVisit = combineQureg.numAmpsPerChunk;
+
2849 
+
2850  int threadsPerCUDABlock, CUDABlocks;
+
2851  threadsPerCUDABlock = 128;
+
2852  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
2853  densmatr_mixDensityMatrixKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2854  combineQureg, otherProb, otherQureg, numAmpsToVisit
+
2855  );
+
2856 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by mixDensityMatrix().

+

Referenced by mixDensityMatrix().

@@ -2871,18 +2871,18 @@

-

Definition at line 2832 of file QuEST_gpu.cu.

-
2832  {
-
2833 
-
2834  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2835  if (ampInd >= numAmpsToVisit) return;
-
2836 
-
2837  combineQureg.deviceStateVec.real[ampInd] *= 1-otherProb;
-
2838  combineQureg.deviceStateVec.imag[ampInd] *= 1-otherProb;
-
2839 
-
2840  combineQureg.deviceStateVec.real[ampInd] += otherProb*otherQureg.deviceStateVec.real[ampInd];
-
2841  combineQureg.deviceStateVec.imag[ampInd] += otherProb*otherQureg.deviceStateVec.imag[ampInd];
-
2842 }
+

Definition at line 2834 of file QuEST_gpu.cu.

+
2834  {
+
2835 
+
2836  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2837  if (ampInd >= numAmpsToVisit) return;
+
2838 
+
2839  combineQureg.deviceStateVec.real[ampInd] *= 1-otherProb;
+
2840  combineQureg.deviceStateVec.imag[ampInd] *= 1-otherProb;
+
2841 
+
2842  combineQureg.deviceStateVec.real[ampInd] += otherProb*otherQureg.deviceStateVec.real[ampInd];
+
2843  combineQureg.deviceStateVec.imag[ampInd] += otherProb*otherQureg.deviceStateVec.imag[ampInd];
+
2844 }

References Qureg::deviceStateVec.

@@ -2920,19 +2920,19 @@

-

Definition at line 2897 of file QuEST_gpu.cu.

-
2897  {
-
2898 
-
2899  if (dephase == 0)
-
2900  return;
-
2901 
-
2902  qreal dephFac = 1 - dephase;
-
2903  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephFac);
-
2904 }
+

Definition at line 2899 of file QuEST_gpu.cu.

+
2899  {
+
2900 
+
2901  if (dephase == 0)
+
2902  return;
+
2903 
+
2904  qreal dephFac = 1 - dephase;
+
2905  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephFac);
+
2906 }
-

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

+

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

-

Referenced by densmatr_mixDepolarising(), and mixDephasing().

+

Referenced by densmatr_mixDepolarising(), and mixDephasing().

@@ -3007,17 +3007,17 @@

Definition at line 2861 of file QuEST_gpu.cu.

-
2865 {
-
2866  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2867  if (scanInd >= numAmpsToVisit) return;
-
2868 
-
2869  long long int ampInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2870  vecReal[ampInd + colBit] *= fac;
-
2871  vecImag[ampInd + colBit] *= fac;
-
2872  vecReal[ampInd + rowBit] *= fac;
-
2873  vecImag[ampInd + rowBit] *= fac;
-
2874 }
+

Definition at line 2863 of file QuEST_gpu.cu.

+
2867 {
+
2868  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2869  if (scanInd >= numAmpsToVisit) return;
+
2870 
+
2871  long long int ampInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2872  vecReal[ampInd + colBit] *= fac;
+
2873  vecImag[ampInd + colBit] *= fac;
+
2874  vecReal[ampInd + rowBit] *= fac;
+
2875  vecImag[ampInd + rowBit] *= fac;
+
2876 }
@@ -3053,36 +3053,36 @@

-

Definition at line 3020 of file QuEST_gpu.cu.

-
3020  {
-
3021 
-
3022  if (depolLevel == 0)
-
3023  return;
-
3024 
-
3025  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+

Definition at line 3022 of file QuEST_gpu.cu.

+
3022  {
+
3023 
+
3024  if (depolLevel == 0)
+
3025  return;
3026 
-
3027  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
3028  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
3029 
-
3030  long long int colBit = 1LL << targetQubit;
-
3031  long long int rowBit = 1LL << rowQubit;
-
3032  long long int bothBits = colBit | rowBit;
-
3033 
-
3034  long long int part1 = colBit - 1;
-
3035  long long int part2 = (rowBit >> 1) - colBit;
-
3036  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
3037 
-
3038  int threadsPerCUDABlock, CUDABlocks;
-
3039  threadsPerCUDABlock = 128;
-
3040  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3041  densmatr_mixDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3042  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
3043  part1, part2, part3, bothBits);
-
3044 }
-
-

References densmatr_mixDephasing(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixDepolarising().

+
3027  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
3028 
+
3029  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
3030  int rowQubit = targetQubit + qureg.numQubitsRepresented;
+
3031 
+
3032  long long int colBit = 1LL << targetQubit;
+
3033  long long int rowBit = 1LL << rowQubit;
+
3034  long long int bothBits = colBit | rowBit;
+
3035 
+
3036  long long int part1 = colBit - 1;
+
3037  long long int part2 = (rowBit >> 1) - colBit;
+
3038  long long int part3 = numAmpsToVisit - (rowBit >> 1);
+
3039 
+
3040  int threadsPerCUDABlock, CUDABlocks;
+
3041  threadsPerCUDABlock = 128;
+
3042  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3043  densmatr_mixDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3044  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
3045  part1, part2, part3, bothBits);
+
3046 }
+
+

References densmatr_mixDephasing(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+ +

Referenced by mixDepolarising().

@@ -3150,27 +3150,27 @@

Definition at line 2973 of file QuEST_gpu.cu.

-
2977 {
-
2978  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2979  if (scanInd >= numAmpsToVisit) return;
-
2980 
-
2981  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2982  long long int targetInd = baseInd + bothBits;
-
2983 
-
2984  qreal realAvDepol = depolLevel * 0.5 * (vecReal[baseInd] + vecReal[targetInd]);
-
2985  qreal imagAvDepol = depolLevel * 0.5 * (vecImag[baseInd] + vecImag[targetInd]);
-
2986 
-
2987  vecReal[baseInd] *= 1 - depolLevel;
-
2988  vecImag[baseInd] *= 1 - depolLevel;
-
2989  vecReal[targetInd] *= 1 - depolLevel;
-
2990  vecImag[targetInd] *= 1 - depolLevel;
-
2991 
-
2992  vecReal[baseInd] += realAvDepol;
-
2993  vecImag[baseInd] += imagAvDepol;
-
2994  vecReal[targetInd] += realAvDepol;
-
2995  vecImag[targetInd] += imagAvDepol;
-
2996 }
+

Definition at line 2975 of file QuEST_gpu.cu.

+
2979 {
+
2980  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2981  if (scanInd >= numAmpsToVisit) return;
+
2982 
+
2983  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2984  long long int targetInd = baseInd + bothBits;
+
2985 
+
2986  qreal realAvDepol = depolLevel * 0.5 * (vecReal[baseInd] + vecReal[targetInd]);
+
2987  qreal imagAvDepol = depolLevel * 0.5 * (vecImag[baseInd] + vecImag[targetInd]);
+
2988 
+
2989  vecReal[baseInd] *= 1 - depolLevel;
+
2990  vecImag[baseInd] *= 1 - depolLevel;
+
2991  vecReal[targetInd] *= 1 - depolLevel;
+
2992  vecImag[targetInd] *= 1 - depolLevel;
+
2993 
+
2994  vecReal[baseInd] += realAvDepol;
+
2995  vecImag[baseInd] += imagAvDepol;
+
2996  vecReal[targetInd] += realAvDepol;
+
2997  vecImag[targetInd] += imagAvDepol;
+
2998 }

References qreal.

@@ -3214,46 +3214,46 @@

-

Definition at line 2936 of file QuEST_gpu.cu.

-
2936  {
-
2937 
-
2938  if (dephase == 0)
-
2939  return;
-
2940 
-
2941  // assumes qubit2 > qubit1
+

Definition at line 2938 of file QuEST_gpu.cu.

+
2938  {
+
2939 
+
2940  if (dephase == 0)
+
2941  return;
2942 
-
2943  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
2944  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
2945 
-
2946  long long int colBit1 = 1LL << qubit1;
-
2947  long long int rowBit1 = 1LL << rowQubit1;
-
2948  long long int colBit2 = 1LL << qubit2;
-
2949  long long int rowBit2 = 1LL << rowQubit2;
-
2950 
-
2951  long long int part1 = colBit1 - 1;
-
2952  long long int part2 = (colBit2 >> 1) - colBit1;
-
2953  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
2954  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
2955  long long int part5 = (qureg.numAmpsPerChunk/16) - (rowBit2 >> 3);
-
2956  qreal dephFac = 1 - dephase;
-
2957 
-
2958  // refers to states |a 0 b 0 c><d 0 e 0 f| (target qubits are fixed)
-
2959  long long int numBackgroundStates = qureg.numAmpsPerChunk/16;
-
2960 
-
2961  // 12 of these states experience dephasing
-
2962  long long int numAmpsToVisit = 12 * numBackgroundStates;
-
2963 
-
2964  int threadsPerCUDABlock, CUDABlocks;
-
2965  threadsPerCUDABlock = 128;
-
2966  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2967  densmatr_mixTwoQubitDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2968  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBackgroundStates, numAmpsToVisit,
-
2969  part1, part2, part3, part4, part5, colBit1, rowBit1, colBit2, rowBit2);
-
2970 }
+
2943  // assumes qubit2 > qubit1
+
2944 
+
2945  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
+
2946  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
+
2947 
+
2948  long long int colBit1 = 1LL << qubit1;
+
2949  long long int rowBit1 = 1LL << rowQubit1;
+
2950  long long int colBit2 = 1LL << qubit2;
+
2951  long long int rowBit2 = 1LL << rowQubit2;
+
2952 
+
2953  long long int part1 = colBit1 - 1;
+
2954  long long int part2 = (colBit2 >> 1) - colBit1;
+
2955  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
+
2956  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
+
2957  long long int part5 = (qureg.numAmpsPerChunk/16) - (rowBit2 >> 3);
+
2958  qreal dephFac = 1 - dephase;
+
2959 
+
2960  // refers to states |a 0 b 0 c><d 0 e 0 f| (target qubits are fixed)
+
2961  long long int numBackgroundStates = qureg.numAmpsPerChunk/16;
+
2962 
+
2963  // 12 of these states experience dephasing
+
2964  long long int numAmpsToVisit = 12 * numBackgroundStates;
+
2965 
+
2966  int threadsPerCUDABlock, CUDABlocks;
+
2967  threadsPerCUDABlock = 128;
+
2968  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
2969  densmatr_mixTwoQubitDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2970  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBackgroundStates, numAmpsToVisit,
+
2971  part1, part2, part3, part4, part5, colBit1, rowBit1, colBit2, rowBit2);
+
2972 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

+

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

@@ -3358,25 +3358,25 @@

Definition at line 2912 of file QuEST_gpu.cu.

-
2916 {
-
2917  long long int outerInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2918  if (outerInd >= numAmpsToVisit) return;
-
2919 
-
2920  // sets meta in 1...14 excluding 5, 10, creating bit string DCBA for |..D..C..><..B..A|
-
2921  int meta = 1 + (outerInd/numBackgroundStates);
-
2922  if (meta > 4) meta++;
-
2923  if (meta > 9) meta++;
-
2924 
-
2925  long long int shift = rowBit2*((meta>>3)%2) + rowBit1*((meta>>2)%2) + colBit2*((meta>>1)%2) + colBit1*(meta%2);
-
2926  long long int scanInd = outerInd % numBackgroundStates;
-
2927  long long int stateInd = (
-
2928  shift +
-
2929  (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4));
-
2930 
-
2931  vecReal[stateInd] *= fac;
-
2932  vecImag[stateInd] *= fac;
-
2933 }
+

Definition at line 2914 of file QuEST_gpu.cu.

+
2918 {
+
2919  long long int outerInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2920  if (outerInd >= numAmpsToVisit) return;
+
2921 
+
2922  // sets meta in 1...14 excluding 5, 10, creating bit string DCBA for |..D..C..><..B..A|
+
2923  int meta = 1 + (outerInd/numBackgroundStates);
+
2924  if (meta > 4) meta++;
+
2925  if (meta > 9) meta++;
+
2926 
+
2927  long long int shift = rowBit2*((meta>>3)%2) + rowBit1*((meta>>2)%2) + colBit2*((meta>>1)%2) + colBit1*(meta%2);
+
2928  long long int scanInd = outerInd % numBackgroundStates;
+
2929  long long int stateInd = (
+
2930  shift +
+
2931  (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4));
+
2932 
+
2933  vecReal[stateInd] *= fac;
+
2934  vecImag[stateInd] *= fac;
+
2935 }
@@ -3418,45 +3418,45 @@

-

Definition at line 3106 of file QuEST_gpu.cu.

-
3106  {
-
3107 
-
3108  if (depolLevel == 0)
-
3109  return;
-
3110 
-
3111  // assumes qubit2 > qubit1
+

Definition at line 3108 of file QuEST_gpu.cu.

+
3108  {
+
3109 
+
3110  if (depolLevel == 0)
+
3111  return;
3112 
-
3113  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
3113  // assumes qubit2 > qubit1
3114 
-
3115  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
3116  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
3117 
-
3118  long long int colBit1 = 1LL << qubit1;
-
3119  long long int rowBit1 = 1LL << rowQubit1;
-
3120  long long int colBit2 = 1LL << qubit2;
-
3121  long long int rowBit2 = 1LL << rowQubit2;
-
3122 
-
3123  long long int rowCol1 = colBit1 | rowBit1;
-
3124  long long int rowCol2 = colBit2 | rowBit2;
-
3125 
-
3126  long long int numAmpsToVisit = qureg.numAmpsPerChunk/16;
-
3127  long long int part1 = colBit1 - 1;
-
3128  long long int part2 = (colBit2 >> 1) - colBit1;
-
3129  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
3130  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
3131  long long int part5 = numAmpsToVisit - (rowBit2 >> 3);
-
3132 
-
3133  int threadsPerCUDABlock, CUDABlocks;
-
3134  threadsPerCUDABlock = 128;
-
3135  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3136  densmatr_mixTwoQubitDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3137  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
3138  part1, part2, part3, part4, part5, rowCol1, rowCol2);
-
3139 }
-
-

References densmatr_mixTwoQubitDephasing(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

- -

Referenced by mixTwoQubitDepolarising().

+
3115  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
3116 
+
3117  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
+
3118  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
+
3119 
+
3120  long long int colBit1 = 1LL << qubit1;
+
3121  long long int rowBit1 = 1LL << rowQubit1;
+
3122  long long int colBit2 = 1LL << qubit2;
+
3123  long long int rowBit2 = 1LL << rowQubit2;
+
3124 
+
3125  long long int rowCol1 = colBit1 | rowBit1;
+
3126  long long int rowCol2 = colBit2 | rowBit2;
+
3127 
+
3128  long long int numAmpsToVisit = qureg.numAmpsPerChunk/16;
+
3129  long long int part1 = colBit1 - 1;
+
3130  long long int part2 = (colBit2 >> 1) - colBit1;
+
3131  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
+
3132  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
+
3133  long long int part5 = numAmpsToVisit - (rowBit2 >> 3);
+
3134 
+
3135  int threadsPerCUDABlock, CUDABlocks;
+
3136  threadsPerCUDABlock = 128;
+
3137  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3138  densmatr_mixTwoQubitDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3139  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
3140  part1, part2, part3, part4, part5, rowCol1, rowCol2);
+
3141 }
+
+

References densmatr_mixTwoQubitDephasing(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+ +

Referenced by mixTwoQubitDepolarising().

@@ -3542,33 +3542,33 @@

Definition at line 3074 of file QuEST_gpu.cu.

-
3079 {
-
3080  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3081  if (scanInd >= numAmpsToVisit) return;
-
3082 
-
3083  // index of |..0..0..><..0..0|
-
3084  long long int ind00 = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4);
-
3085  long long int ind01 = ind00 + rowCol1;
-
3086  long long int ind10 = ind00 + rowCol2;
-
3087  long long int ind11 = ind00 + rowCol1 + rowCol2;
-
3088 
-
3089  qreal realAvDepol = depolLevel * 0.25 * (
-
3090  vecReal[ind00] + vecReal[ind01] + vecReal[ind10] + vecReal[ind11]);
-
3091  qreal imagAvDepol = depolLevel * 0.25 * (
-
3092  vecImag[ind00] + vecImag[ind01] + vecImag[ind10] + vecImag[ind11]);
-
3093 
-
3094  qreal retain = 1 - depolLevel;
-
3095  vecReal[ind00] *= retain; vecImag[ind00] *= retain;
-
3096  vecReal[ind01] *= retain; vecImag[ind01] *= retain;
-
3097  vecReal[ind10] *= retain; vecImag[ind10] *= retain;
-
3098  vecReal[ind11] *= retain; vecImag[ind11] *= retain;
-
3099 
-
3100  vecReal[ind00] += realAvDepol; vecImag[ind00] += imagAvDepol;
-
3101  vecReal[ind01] += realAvDepol; vecImag[ind01] += imagAvDepol;
-
3102  vecReal[ind10] += realAvDepol; vecImag[ind10] += imagAvDepol;
-
3103  vecReal[ind11] += realAvDepol; vecImag[ind11] += imagAvDepol;
-
3104 }
+

Definition at line 3076 of file QuEST_gpu.cu.

+
3081 {
+
3082  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3083  if (scanInd >= numAmpsToVisit) return;
+
3084 
+
3085  // index of |..0..0..><..0..0|
+
3086  long long int ind00 = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4);
+
3087  long long int ind01 = ind00 + rowCol1;
+
3088  long long int ind10 = ind00 + rowCol2;
+
3089  long long int ind11 = ind00 + rowCol1 + rowCol2;
+
3090 
+
3091  qreal realAvDepol = depolLevel * 0.25 * (
+
3092  vecReal[ind00] + vecReal[ind01] + vecReal[ind10] + vecReal[ind11]);
+
3093  qreal imagAvDepol = depolLevel * 0.25 * (
+
3094  vecImag[ind00] + vecImag[ind01] + vecImag[ind10] + vecImag[ind11]);
+
3095 
+
3096  qreal retain = 1 - depolLevel;
+
3097  vecReal[ind00] *= retain; vecImag[ind00] *= retain;
+
3098  vecReal[ind01] *= retain; vecImag[ind01] *= retain;
+
3099  vecReal[ind10] *= retain; vecImag[ind10] *= retain;
+
3100  vecReal[ind11] *= retain; vecImag[ind11] *= retain;
+
3101 
+
3102  vecReal[ind00] += realAvDepol; vecImag[ind00] += imagAvDepol;
+
3103  vecReal[ind01] += realAvDepol; vecImag[ind01] += imagAvDepol;
+
3104  vecReal[ind10] += realAvDepol; vecImag[ind10] += imagAvDepol;
+
3105  vecReal[ind11] += realAvDepol; vecImag[ind11] += imagAvDepol;
+
3106 }

References qreal.

@@ -3606,30 +3606,30 @@

-

Definition at line 2877 of file QuEST_gpu.cu.

-
2877  {
-
2878 
-
2879  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+

Definition at line 2879 of file QuEST_gpu.cu.

+
2879  {
2880 
-
2881  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2882  long long int colBit = 1LL << targetQubit;
-
2883  long long int rowBit = 1LL << rowQubit;
-
2884 
-
2885  long long int part1 = colBit - 1;
-
2886  long long int part2 = (rowBit >> 1) - colBit;
-
2887  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2888 
-
2889  int threadsPerCUDABlock, CUDABlocks;
-
2890  threadsPerCUDABlock = 128;
-
2891  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2892  densmatr_mixDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2893  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2894  part1, part2, part3, colBit, rowBit);
-
2895 }
+
2881  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
2882 
+
2883  int rowQubit = targetQubit + qureg.numQubitsRepresented;
+
2884  long long int colBit = 1LL << targetQubit;
+
2885  long long int rowBit = 1LL << rowQubit;
+
2886 
+
2887  long long int part1 = colBit - 1;
+
2888  long long int part2 = (rowBit >> 1) - colBit;
+
2889  long long int part3 = numAmpsToVisit - (rowBit >> 1);
+
2890 
+
2891  int threadsPerCUDABlock, CUDABlocks;
+
2892  threadsPerCUDABlock = 128;
+
2893  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
2894  densmatr_mixDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2895  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
2896  part1, part2, part3, colBit, rowBit);
+
2897 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by densmatr_mixDamping(), and densmatr_mixDephasing().

+

Referenced by densmatr_mixDamping(), and densmatr_mixDephasing().

@@ -3664,7 +3664,7 @@

83  return (theEncodedNumber & ( 1LL << locationOfBitFromRight )) >> locationOfBitFromRight;
84 }
-

Referenced by agnostic_initDiagonalOpFromPauliHamil(), agnostic_initDiagonalOpFromPauliHamilKernel(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), densmatr_calcProbOfAllOutcomesKernel(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroLocal(), densmatr_mixDampingDistributed(), densmatr_mixDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), getGlobalIndOfOddParityInChunk(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyMultiVarPhaseFuncOverridesKernel(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverridesKernel(), statevec_applyPhaseFuncOverrides(), statevec_applyPhaseFuncOverridesKernel(), statevec_calcProbOfAllOutcomesKernel(), statevec_calcProbOfAllOutcomesLocal(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNotDistributed(), statevec_controlledNotKernel(), statevec_controlledNotLocal(), statevec_controlledPauliYDistributed(), statevec_controlledPauliYKernel(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseFlipKernel(), statevec_controlledPhaseShift(), statevec_controlledPhaseShiftKernel(), statevec_controlledUnitaryDistributed(), statevec_controlledUnitaryKernel(), statevec_controlledUnitaryLocal(), statevec_initStateOfSingleQubit(), statevec_initStateOfSingleQubitKernel(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_phaseShiftByTerm().

+

Referenced by agnostic_initDiagonalOpFromPauliHamil(), agnostic_initDiagonalOpFromPauliHamilKernel(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), densmatr_calcProbOfAllOutcomesKernel(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroLocal(), densmatr_mixDampingDistributed(), densmatr_mixDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), getGlobalIndOfOddParityInChunk(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyMultiVarPhaseFuncOverridesKernel(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverridesKernel(), statevec_applyPhaseFuncOverrides(), statevec_applyPhaseFuncOverridesKernel(), statevec_calcProbOfAllOutcomesKernel(), statevec_calcProbOfAllOutcomesLocal(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNotDistributed(), statevec_controlledNotKernel(), statevec_controlledNotLocal(), statevec_controlledPauliYDistributed(), statevec_controlledPauliYKernel(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseFlipKernel(), statevec_controlledPhaseShift(), statevec_controlledPhaseShiftKernel(), statevec_controlledUnitaryDistributed(), statevec_controlledUnitaryKernel(), statevec_controlledUnitaryLocal(), statevec_initStateOfSingleQubit(), statevec_initStateOfSingleQubitKernel(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_phaseShiftByTerm().

@@ -3699,7 +3699,7 @@

96  return (number ^ (1LL << bitInd));
97 }
-

Referenced by getGlobalIndOfOddParityInChunk(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledTwoQubitUnitary(), statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_swapQubitAmps(), statevec_swapQubitAmpsDistributed(), statevec_swapQubitAmpsKernel(), and statevec_swapQubitAmpsLocal().

+

Referenced by getGlobalIndOfOddParityInChunk(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledTwoQubitUnitary(), statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_swapQubitAmps(), statevec_swapQubitAmpsDistributed(), statevec_swapQubitAmpsKernel(), and statevec_swapQubitAmpsLocal().

@@ -3729,7 +3729,7 @@

92  return parity;
93 }
-

Referenced by statevec_multiControlledMultiRotateZKernel(), and statevec_multiRotateZKernel().

+

Referenced by statevec_multiControlledMultiRotateZKernel(), and statevec_multiRotateZKernel().

@@ -3759,15 +3759,15 @@

-

Definition at line 2046 of file QuEST_gpu.cu.

-
2046  {
-
2047  int levels=0;
-
2048  while (numValuesToReduce){
-
2049  numValuesToReduce = numValuesToReduce/numReducedPerLevel;
-
2050  levels++;
-
2051  }
-
2052  return levels;
-
2053 }
+

Definition at line 2048 of file QuEST_gpu.cu.

+
2048  {
+
2049  int levels=0;
+
2050  while (numValuesToReduce){
+
2051  numValuesToReduce = numValuesToReduce/numReducedPerLevel;
+
2052  levels++;
+
2053  }
+
2054  return levels;
+
2055 }
@@ -3850,7 +3850,7 @@

References insertZeroBit().

-

Referenced by statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_swapQubitAmpsKernel(), and statevec_swapQubitAmpsLocal().

+

Referenced by statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_swapQubitAmpsKernel(), and statevec_swapQubitAmpsLocal().

@@ -3888,7 +3888,7 @@

103  return (left << 1) ^ right;
104 }
-

Referenced by insertTwoZeroBits(), insertZeroBits(), and statevec_multiControlledMultiQubitUnitaryLocal().

+

Referenced by insertTwoZeroBits(), insertZeroBits(), and statevec_multiControlledMultiQubitUnitaryLocal().

@@ -3957,7 +3957,7 @@

References insertZeroBit().

-

Referenced by statevec_multiControlledMultiQubitUnitaryKernel().

+

Referenced by statevec_multiControlledMultiQubitUnitaryKernel().

@@ -3977,14 +3977,14 @@

-

Definition at line 1923 of file QuEST_gpu.cu.

-
1924 {
-
1925  unsigned int ans = 0 ;
-
1926  while( x>>=1 ) ans++;
-
1927  return ans ;
-
1928 }
+

Definition at line 1925 of file QuEST_gpu.cu.

+
1926 {
+
1927  unsigned int ans = 0 ;
+
1928  while( x>>=1 ) ans++;
+
1929  return ans ;
+
1930 }
-

Referenced by reduceBlock().

+

Referenced by reduceBlock().

@@ -4020,29 +4020,29 @@

-

Definition at line 1930 of file QuEST_gpu.cu.

-
1930  {
-
1931  int i, l, r;
-
1932  int threadMax, maxDepth;
-
1933  threadMax = length/2;
-
1934  maxDepth = log2Int(length/2);
-
1935 
-
1936  for (i=0; i<maxDepth+1; i++){
-
1937  if (threadIdx.x<threadMax){
-
1938  l = threadIdx.x;
-
1939  r = l + threadMax;
-
1940  arrayIn[l] = arrayIn[r] + arrayIn[l];
-
1941  }
-
1942  threadMax = threadMax >> 1;
-
1943  __syncthreads(); // optimise -- use warp shuffle instead
-
1944  }
-
1945 
-
1946  if (threadIdx.x==0) reducedArray[blockIdx.x] = arrayIn[0];
-
1947 }
+

Definition at line 1932 of file QuEST_gpu.cu.

+
1932  {
+
1933  int i, l, r;
+
1934  int threadMax, maxDepth;
+
1935  threadMax = length/2;
+
1936  maxDepth = log2Int(length/2);
+
1937 
+
1938  for (i=0; i<maxDepth+1; i++){
+
1939  if (threadIdx.x<threadMax){
+
1940  l = threadIdx.x;
+
1941  r = l + threadMax;
+
1942  arrayIn[l] = arrayIn[r] + arrayIn[l];
+
1943  }
+
1944  threadMax = threadMax >> 1;
+
1945  __syncthreads(); // optimise -- use warp shuffle instead
+
1946  }
+
1947 
+
1948  if (threadIdx.x==0) reducedArray[blockIdx.x] = arrayIn[0];
+
1949 }
-

References log2Int().

+

References log2Int().

-

Referenced by copySharedReduceBlock(), densmatr_calcExpecDiagonalOpKernel(), densmatr_calcFidelityKernel(), densmatr_calcHilbertSchmidtDistanceSquaredKernel(), densmatr_calcInnerProductKernel(), densmatr_calcPurityKernel(), densmatr_findProbabilityOfZeroKernel(), statevec_calcExpecDiagonalOpKernel(), statevec_calcInnerProductKernel(), and statevec_findProbabilityOfZeroKernel().

+

Referenced by copySharedReduceBlock(), densmatr_calcExpecDiagonalOpKernel(), densmatr_calcFidelityKernel(), densmatr_calcHilbertSchmidtDistanceSquaredKernel(), densmatr_calcInnerProductKernel(), densmatr_calcPurityKernel(), densmatr_findProbabilityOfZeroKernel(), statevec_calcExpecDiagonalOpKernel(), statevec_calcInnerProductKernel(), and statevec_findProbabilityOfZeroKernel().

@@ -4072,17 +4072,17 @@

-

Definition at line 3207 of file QuEST_gpu.cu.

-
3208 {
-
3209  int threadsPerCUDABlock, CUDABlocks;
-
3210  threadsPerCUDABlock = 128;
-
3211  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
3212  statevec_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
3213 }
+

Definition at line 3209 of file QuEST_gpu.cu.

+
3210 {
+
3211  int threadsPerCUDABlock, CUDABlocks;
+
3212  threadsPerCUDABlock = 128;
+
3213  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
3214  statevec_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
+
3215 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by applyDiagonalOp().

+

Referenced by applyDiagonalOp().

@@ -4112,28 +4112,28 @@

-

Definition at line 3185 of file QuEST_gpu.cu.

-
3185  {
-
3186 
-
3187  // each thread modifies one value; a wasteful and inefficient strategy
-
3188  long long int numTasks = qureg.numAmpsPerChunk;
-
3189  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
3190  if (thisTask >= numTasks) return;
-
3191 
-
3192  qreal* stateRe = qureg.deviceStateVec.real;
-
3193  qreal* stateIm = qureg.deviceStateVec.imag;
-
3194  qreal* opRe = op.deviceOperator.real;
-
3195  qreal* opIm = op.deviceOperator.imag;
-
3196 
-
3197  qreal a = stateRe[thisTask];
-
3198  qreal b = stateIm[thisTask];
-
3199  qreal c = opRe[thisTask];
-
3200  qreal d = opIm[thisTask];
-
3201 
-
3202  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3203  stateRe[thisTask] = a*c - b*d;
-
3204  stateIm[thisTask] = a*d + b*c;
-
3205 }
+

Definition at line 3187 of file QuEST_gpu.cu.

+
3187  {
+
3188 
+
3189  // each thread modifies one value; a wasteful and inefficient strategy
+
3190  long long int numTasks = qureg.numAmpsPerChunk;
+
3191  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
3192  if (thisTask >= numTasks) return;
+
3193 
+
3194  qreal* stateRe = qureg.deviceStateVec.real;
+
3195  qreal* stateIm = qureg.deviceStateVec.imag;
+
3196  qreal* opRe = op.deviceOperator.real;
+
3197  qreal* opIm = op.deviceOperator.imag;
+
3198 
+
3199  qreal a = stateRe[thisTask];
+
3200  qreal b = stateIm[thisTask];
+
3201  qreal c = opRe[thisTask];
+
3202  qreal d = opIm[thisTask];
+
3203 
+
3204  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
3205  stateRe[thisTask] = a*c - b*d;
+
3206  stateIm[thisTask] = a*d + b*c;
+
3207 }

References DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -4225,70 +4225,70 @@

-

Definition at line 3693 of file QuEST_gpu.cu.

-
3698  {
-
3699  // determine size of arrays, for cloning into GPU memory
-
3700  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
-
3701  size_t mem_numTermsPerReg = numRegs * sizeof *numTermsPerReg;
-
3702  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
-
3703  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
-
3704  size_t mem_qubits = 0;
-
3705  size_t mem_coeffs = 0;
-
3706  size_t mem_exponents = 0;
-
3707  for (int r=0; r<numRegs; r++) {
-
3708  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
-
3709  mem_coeffs += numTermsPerReg[r] * sizeof *coeffs;
-
3710  mem_exponents += numTermsPerReg[r] * sizeof *exponents;
-
3711  }
-
3712 
-
3713  // allocate global GPU memory
-
3714  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
-
3715  qreal* d_coeffs; cudaMalloc(&d_coeffs, mem_coeffs);
-
3716  qreal* d_exponents; cudaMalloc(&d_exponents, mem_exponents);
-
3717  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
-
3718  int* d_numTermsPerReg; cudaMalloc(&d_numTermsPerReg, mem_numTermsPerReg);
-
3719  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
-
3720  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
-
3721 
-
3722  // copy function args into GPU memory
-
3723  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
3724  cudaMemcpy(d_coeffs, coeffs, mem_coeffs, cudaMemcpyHostToDevice);
-
3725  cudaMemcpy(d_exponents, exponents, mem_exponents, cudaMemcpyHostToDevice);
-
3726  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
-
3727  cudaMemcpy(d_numTermsPerReg, numTermsPerReg, mem_numTermsPerReg, cudaMemcpyHostToDevice);
-
3728  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
-
3729  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
-
3730 
-
3731  int threadsPerCUDABlock = 128;
-
3732  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
-
3733 
-
3734  // allocate thread-local working space {phaseInds}
-
3735  long long int *d_phaseInds;
-
3736  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
3737  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
-
3738 
-
3739  // call kernel
-
3740  statevec_applyMultiVarPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
3741  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
-
3742  d_coeffs, d_exponents, d_numTermsPerReg,
-
3743  d_overrideInds, d_overridePhases, numOverrides,
-
3744  d_phaseInds,
-
3745  conj);
-
3746 
-
3747  // free device memory
-
3748  cudaFree(d_qubits);
-
3749  cudaFree(d_coeffs);
-
3750  cudaFree(d_exponents);
-
3751  cudaFree(d_numQubitsPerReg);
-
3752  cudaFree(d_numTermsPerReg);
-
3753  cudaFree(d_overrideInds);
-
3754  cudaFree(d_overridePhases);
-
3755  cudaFree(d_phaseInds);
-
3756 }
+

Definition at line 3695 of file QuEST_gpu.cu.

+
3700  {
+
3701  // determine size of arrays, for cloning into GPU memory
+
3702  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
+
3703  size_t mem_numTermsPerReg = numRegs * sizeof *numTermsPerReg;
+
3704  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
+
3705  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
+
3706  size_t mem_qubits = 0;
+
3707  size_t mem_coeffs = 0;
+
3708  size_t mem_exponents = 0;
+
3709  for (int r=0; r<numRegs; r++) {
+
3710  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
+
3711  mem_coeffs += numTermsPerReg[r] * sizeof *coeffs;
+
3712  mem_exponents += numTermsPerReg[r] * sizeof *exponents;
+
3713  }
+
3714 
+
3715  // allocate global GPU memory
+
3716  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
+
3717  qreal* d_coeffs; cudaMalloc(&d_coeffs, mem_coeffs);
+
3718  qreal* d_exponents; cudaMalloc(&d_exponents, mem_exponents);
+
3719  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
+
3720  int* d_numTermsPerReg; cudaMalloc(&d_numTermsPerReg, mem_numTermsPerReg);
+
3721  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
+
3722  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
+
3723 
+
3724  // copy function args into GPU memory
+
3725  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
3726  cudaMemcpy(d_coeffs, coeffs, mem_coeffs, cudaMemcpyHostToDevice);
+
3727  cudaMemcpy(d_exponents, exponents, mem_exponents, cudaMemcpyHostToDevice);
+
3728  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
+
3729  cudaMemcpy(d_numTermsPerReg, numTermsPerReg, mem_numTermsPerReg, cudaMemcpyHostToDevice);
+
3730  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
+
3731  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
+
3732 
+
3733  int threadsPerCUDABlock = 128;
+
3734  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
+
3735 
+
3736  // allocate thread-local working space {phaseInds}
+
3737  long long int *d_phaseInds;
+
3738  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
+
3739  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
+
3740 
+
3741  // call kernel
+
3742  statevec_applyMultiVarPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
3743  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
+
3744  d_coeffs, d_exponents, d_numTermsPerReg,
+
3745  d_overrideInds, d_overridePhases, numOverrides,
+
3746  d_phaseInds,
+
3747  conj);
+
3748 
+
3749  // free device memory
+
3750  cudaFree(d_qubits);
+
3751  cudaFree(d_coeffs);
+
3752  cudaFree(d_exponents);
+
3753  cudaFree(d_numQubitsPerReg);
+
3754  cudaFree(d_numTermsPerReg);
+
3755  cudaFree(d_overrideInds);
+
3756  cudaFree(d_overridePhases);
+
3757  cudaFree(d_phaseInds);
+
3758 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

@@ -4384,84 +4384,84 @@

-

Definition at line 3609 of file QuEST_gpu.cu.

-
3615  {
-
3616  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3617  if (index>=qureg.numAmpsPerChunk) return;
-
3618 
-
3619  // determine global amplitude index (non-distributed, so it's just local index)
-
3620  long long int globalAmpInd = index;
-
3621 
-
3622  /*
-
3623  * each thread needs to write to a local:
-
3624  * long long int phaseInds[numRegs];
-
3625  * but instead has access to shared array phaseInds, with below stride and offset
-
3626  */
-
3627  size_t stride = gridDim.x*blockDim.x;
-
3628  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
3629 
-
3630  // determine phase indices
-
3631  int flatInd = 0;
-
3632  if (encoding == UNSIGNED) {
-
3633  for (int r=0; r<numRegs; r++) {
-
3634  phaseInds[r*stride+offset] = 0LL;
-
3635  for (int q=0; q<numQubitsPerReg[r]; q++)
-
3636  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3637  }
-
3638  }
-
3639  else if (encoding == TWOS_COMPLEMENT) {
-
3640  for (int r=0; r<numRegs; r++) {
-
3641  phaseInds[r*stride+offset] = 0LL;
-
3642  for (int q=0; q<numQubitsPerReg[r]-1; q++)
-
3643  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3644  // use final qubit to indicate sign
-
3645  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
3646  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
-
3647  }
-
3648  }
-
3649 
-
3650  // determine if this phase index has an overriden value (i < numOverrides)
-
3651  int i;
-
3652  for (i=0; i<numOverrides; i++) {
-
3653  int found = 1;
-
3654  for (int r=0; r<numRegs; r++) {
-
3655  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
-
3656  found = 0;
-
3657  break;
-
3658  }
-
3659  }
-
3660  if (found)
-
3661  break;
-
3662  }
-
3663 
-
3664  // compute the phase (unless overriden)
-
3665  qreal phase = 0;
-
3666  if (i < numOverrides)
-
3667  phase = overridePhases[i];
-
3668  else {
-
3669  flatInd = 0;
-
3670  for (int r=0; r<numRegs; r++) {
-
3671  for (int t=0; t<numTermsPerReg[r]; t++) {
-
3672  phase += coeffs[flatInd] * pow(phaseInds[r*stride+offset], exponents[flatInd]);
-
3673  flatInd++;
-
3674  }
-
3675  }
-
3676  }
-
3677 
-
3678  // negate phase to conjugate operator
-
3679  if (conj)
-
3680  phase *= -1;
-
3681 
-
3682  // modify amp to amp * exp(i phase)
-
3683  qreal c = cos(phase);
-
3684  qreal s = sin(phase);
-
3685  qreal re = qureg.deviceStateVec.real[index];
-
3686  qreal im = qureg.deviceStateVec.imag[index];
-
3687 
-
3688  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
3689  qureg.deviceStateVec.real[index] = re*c - im*s;
-
3690  qureg.deviceStateVec.imag[index] = re*s + im*c;
-
3691 }
+

Definition at line 3611 of file QuEST_gpu.cu.

+
3617  {
+
3618  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3619  if (index>=qureg.numAmpsPerChunk) return;
+
3620 
+
3621  // determine global amplitude index (non-distributed, so it's just local index)
+
3622  long long int globalAmpInd = index;
+
3623 
+
3624  /*
+
3625  * each thread needs to write to a local:
+
3626  * long long int phaseInds[numRegs];
+
3627  * but instead has access to shared array phaseInds, with below stride and offset
+
3628  */
+
3629  size_t stride = gridDim.x*blockDim.x;
+
3630  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
+
3631 
+
3632  // determine phase indices
+
3633  int flatInd = 0;
+
3634  if (encoding == UNSIGNED) {
+
3635  for (int r=0; r<numRegs; r++) {
+
3636  phaseInds[r*stride+offset] = 0LL;
+
3637  for (int q=0; q<numQubitsPerReg[r]; q++)
+
3638  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3639  }
+
3640  }
+
3641  else if (encoding == TWOS_COMPLEMENT) {
+
3642  for (int r=0; r<numRegs; r++) {
+
3643  phaseInds[r*stride+offset] = 0LL;
+
3644  for (int q=0; q<numQubitsPerReg[r]-1; q++)
+
3645  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3646  // use final qubit to indicate sign
+
3647  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
3648  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
+
3649  }
+
3650  }
+
3651 
+
3652  // determine if this phase index has an overriden value (i < numOverrides)
+
3653  int i;
+
3654  for (i=0; i<numOverrides; i++) {
+
3655  int found = 1;
+
3656  for (int r=0; r<numRegs; r++) {
+
3657  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
+
3658  found = 0;
+
3659  break;
+
3660  }
+
3661  }
+
3662  if (found)
+
3663  break;
+
3664  }
+
3665 
+
3666  // compute the phase (unless overriden)
+
3667  qreal phase = 0;
+
3668  if (i < numOverrides)
+
3669  phase = overridePhases[i];
+
3670  else {
+
3671  flatInd = 0;
+
3672  for (int r=0; r<numRegs; r++) {
+
3673  for (int t=0; t<numTermsPerReg[r]; t++) {
+
3674  phase += coeffs[flatInd] * pow(phaseInds[r*stride+offset], exponents[flatInd]);
+
3675  flatInd++;
+
3676  }
+
3677  }
+
3678  }
+
3679 
+
3680  // negate phase to conjugate operator
+
3681  if (conj)
+
3682  phase *= -1;
+
3683 
+
3684  // modify amp to amp * exp(i phase)
+
3685  qreal c = cos(phase);
+
3686  qreal s = sin(phase);
+
3687  qreal re = qureg.deviceStateVec.real[index];
+
3688  qreal im = qureg.deviceStateVec.imag[index];
+
3689 
+
3690  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
3691  qureg.deviceStateVec.real[index] = re*c - im*s;
+
3692  qureg.deviceStateVec.imag[index] = re*s + im*c;
+
3693 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, qreal, TWOS_COMPLEMENT, and UNSIGNED.

@@ -4553,61 +4553,61 @@

-

Definition at line 3907 of file QuEST_gpu.cu.

-
3912  {
-
3913  // determine size of arrays, for cloning into GPU memory
-
3914  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
-
3915  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
-
3916  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
-
3917  size_t mem_params = numParams * sizeof *params;
-
3918  size_t mem_qubits = 0;
-
3919  for (int r=0; r<numRegs; r++)
-
3920  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
-
3921 
-
3922  // allocate global GPU memory
-
3923  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
-
3924  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
-
3925  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
-
3926  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
-
3927  qreal* d_params = NULL; if (numParams > 0) cudaMalloc(&d_params, mem_params);
-
3928 
-
3929  // copy function args into GPU memory
-
3930  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
3931  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
-
3932  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
-
3933  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
-
3934  if (numParams > 0)
-
3935  cudaMemcpy(d_params, params, mem_params, cudaMemcpyHostToDevice);
-
3936 
-
3937  int threadsPerCUDABlock = 128;
-
3938  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
-
3939 
-
3940  // allocate thread-local working space {phaseInds}
-
3941  long long int *d_phaseInds;
-
3942  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
3943  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
-
3944 
-
3945  // call kernel
-
3946  statevec_applyParamNamedPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
3947  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
-
3948  phaseFuncName, d_params, numParams,
-
3949  d_overrideInds, d_overridePhases, numOverrides,
-
3950  d_phaseInds,
-
3951  conj);
-
3952 
-
3953  // free device memory
-
3954  cudaFree(d_qubits);
-
3955  cudaFree(d_numQubitsPerReg);
-
3956  cudaFree(d_overrideInds);
-
3957  cudaFree(d_overridePhases);
-
3958  cudaFree(d_phaseInds);
-
3959  if (numParams > 0)
-
3960  cudaFree(d_params);
-
3961 }
+

Definition at line 3909 of file QuEST_gpu.cu.

+
3914  {
+
3915  // determine size of arrays, for cloning into GPU memory
+
3916  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
+
3917  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
+
3918  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
+
3919  size_t mem_params = numParams * sizeof *params;
+
3920  size_t mem_qubits = 0;
+
3921  for (int r=0; r<numRegs; r++)
+
3922  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
+
3923 
+
3924  // allocate global GPU memory
+
3925  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
+
3926  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
+
3927  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
+
3928  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
+
3929  qreal* d_params = NULL; if (numParams > 0) cudaMalloc(&d_params, mem_params);
+
3930 
+
3931  // copy function args into GPU memory
+
3932  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
3933  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
+
3934  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
+
3935  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
+
3936  if (numParams > 0)
+
3937  cudaMemcpy(d_params, params, mem_params, cudaMemcpyHostToDevice);
+
3938 
+
3939  int threadsPerCUDABlock = 128;
+
3940  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
+
3941 
+
3942  // allocate thread-local working space {phaseInds}
+
3943  long long int *d_phaseInds;
+
3944  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
+
3945  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
+
3946 
+
3947  // call kernel
+
3948  statevec_applyParamNamedPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
3949  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
+
3950  phaseFuncName, d_params, numParams,
+
3951  d_overrideInds, d_overridePhases, numOverrides,
+
3952  d_phaseInds,
+
3953  conj);
+
3954 
+
3955  // free device memory
+
3956  cudaFree(d_qubits);
+
3957  cudaFree(d_numQubitsPerReg);
+
3958  cudaFree(d_overrideInds);
+
3959  cudaFree(d_overridePhases);
+
3960  cudaFree(d_phaseInds);
+
3961  if (numParams > 0)
+
3962  cudaFree(d_params);
+
3963 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -4703,149 +4703,149 @@

-

Definition at line 3758 of file QuEST_gpu.cu.

-
3764  {
-
3765  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3766  if (index>=qureg.numAmpsPerChunk) return;
-
3767 
-
3768  // determine global amplitude index (non-distributed, so it's just local index)
-
3769  long long int globalAmpInd = index;
-
3770 
-
3771  /*
-
3772  * each thread needs to write to a local:
-
3773  * long long int phaseInds[numRegs];
-
3774  * but instead has access to shared array phaseInds, with below stride and offset
-
3775  */
-
3776  size_t stride = gridDim.x*blockDim.x;
-
3777  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
3778 
-
3779  // determine phase indices
-
3780  if (encoding == UNSIGNED) {
-
3781  int flatInd = 0;
-
3782  for (int r=0; r<numRegs; r++) {
-
3783  phaseInds[r*stride+offset] = 0LL;
-
3784  for (int q=0; q<numQubitsPerReg[r]; q++)
-
3785  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3786  }
-
3787  }
-
3788  else if (encoding == TWOS_COMPLEMENT) {
-
3789  int flatInd = 0;
-
3790  for (int r=0; r<numRegs; r++) {
-
3791  phaseInds[r*stride+offset] = 0LL;
-
3792  for (int q=0; q<numQubitsPerReg[r]-1; q++)
-
3793  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3794  // use final qubit to indicate sign
-
3795  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
3796  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
-
3797  }
-
3798  }
-
3799 
-
3800  // determine if this phase index has an overriden value (i < numOverrides)
-
3801  int i;
-
3802  for (i=0; i<numOverrides; i++) {
-
3803  int found = 1;
-
3804  for (int r=0; r<numRegs; r++) {
-
3805  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
-
3806  found = 0;
-
3807  break;
-
3808  }
-
3809  }
-
3810  if (found)
-
3811  break;
-
3812  }
-
3813 
-
3814  // compute the phase (unless overriden)
-
3815  qreal phase = 0;
-
3816  if (i < numOverrides)
-
3817  phase = overridePhases[i];
-
3818  else {
-
3819  // compute norm related phases
-
3820  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
-
3821  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
-
3822  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
3823  qreal norm = 0;
-
3824  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
3825  for (int r=0; r<numRegs; r++) {
-
3826  qreal dif = phaseInds[r*stride+offset] - params[2+r];
-
3827  norm += dif*dif;
-
3828  }
-
3829  }
-
3830  else
-
3831  for (int r=0; r<numRegs; r++)
-
3832  norm += phaseInds[r*stride+offset]*phaseInds[r*stride+offset];
-
3833  norm = sqrt(norm);
-
3834 
-
3835  if (phaseFuncName == NORM)
-
3836  phase = norm;
-
3837  else if (phaseFuncName == INVERSE_NORM)
-
3838  phase = (norm == 0.)? params[0] : 1/norm;
-
3839  else if (phaseFuncName == SCALED_NORM)
-
3840  phase = params[0] * norm;
-
3841  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
-
3842  phase = (norm == 0.)? params[1] : params[0] / norm;
-
3843  }
-
3844  // compute product related phases
-
3845  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
-
3846  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
-
3847 
-
3848  qreal prod = 1;
-
3849  for (int r=0; r<numRegs; r++)
-
3850  prod *= phaseInds[r*stride+offset];
-
3851 
-
3852  if (phaseFuncName == PRODUCT)
-
3853  phase = prod;
-
3854  else if (phaseFuncName == INVERSE_PRODUCT)
-
3855  phase = (prod == 0.)? params[0] : 1/prod;
-
3856  else if (phaseFuncName == SCALED_PRODUCT)
-
3857  phase = params[0] * prod;
-
3858  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
-
3859  phase = (prod == 0.)? params[1] : params[0] / prod;
-
3860  }
-
3861  // compute Euclidean distance related phases
-
3862  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
-
3863  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
-
3864  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
3865 
-
3866  qreal dist = 0;
-
3867  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
3868  for (int r=0; r<numRegs; r+=2) {
-
3869  qreal dif = (phaseInds[(r+1)*stride+offset] - phaseInds[r*stride+offset] - params[2+r/2]);
-
3870  dist += dif*dif;
-
3871  }
-
3872  }
-
3873  else
-
3874  for (int r=0; r<numRegs; r+=2) {
-
3875  qreal dif = (phaseInds[(r+1)*stride+offset] - phaseInds[r*stride+offset]);
-
3876  dist += dif*dif;
-
3877  }
-
3878  dist = sqrt(dist);
-
3879 
-
3880  if (phaseFuncName == DISTANCE)
-
3881  phase = dist;
-
3882  else if (phaseFuncName == INVERSE_DISTANCE)
-
3883  phase = (dist == 0.)? params[0] : 1/dist;
-
3884  else if (phaseFuncName == SCALED_DISTANCE)
-
3885  phase = params[0] * dist;
-
3886  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
-
3887  phase = (dist == 0.)? params[1] : params[0] / dist;
-
3888  }
-
3889  }
-
3890 
-
3891 
-
3892  // negate phase to conjugate operator
-
3893  if (conj)
-
3894  phase *= -1;
-
3895 
-
3896  // modify amp to amp * exp(i phase)
-
3897  qreal c = cos(phase);
-
3898  qreal s = sin(phase);
-
3899  qreal re = qureg.deviceStateVec.real[index];
-
3900  qreal im = qureg.deviceStateVec.imag[index];
-
3901 
-
3902  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
3903  qureg.deviceStateVec.real[index] = re*c - im*s;
-
3904  qureg.deviceStateVec.imag[index] = re*s + im*c;
-
3905 }
+

Definition at line 3760 of file QuEST_gpu.cu.

+
3766  {
+
3767  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3768  if (index>=qureg.numAmpsPerChunk) return;
+
3769 
+
3770  // determine global amplitude index (non-distributed, so it's just local index)
+
3771  long long int globalAmpInd = index;
+
3772 
+
3773  /*
+
3774  * each thread needs to write to a local:
+
3775  * long long int phaseInds[numRegs];
+
3776  * but instead has access to shared array phaseInds, with below stride and offset
+
3777  */
+
3778  size_t stride = gridDim.x*blockDim.x;
+
3779  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
+
3780 
+
3781  // determine phase indices
+
3782  if (encoding == UNSIGNED) {
+
3783  int flatInd = 0;
+
3784  for (int r=0; r<numRegs; r++) {
+
3785  phaseInds[r*stride+offset] = 0LL;
+
3786  for (int q=0; q<numQubitsPerReg[r]; q++)
+
3787  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3788  }
+
3789  }
+
3790  else if (encoding == TWOS_COMPLEMENT) {
+
3791  int flatInd = 0;
+
3792  for (int r=0; r<numRegs; r++) {
+
3793  phaseInds[r*stride+offset] = 0LL;
+
3794  for (int q=0; q<numQubitsPerReg[r]-1; q++)
+
3795  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3796  // use final qubit to indicate sign
+
3797  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
3798  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
+
3799  }
+
3800  }
+
3801 
+
3802  // determine if this phase index has an overriden value (i < numOverrides)
+
3803  int i;
+
3804  for (i=0; i<numOverrides; i++) {
+
3805  int found = 1;
+
3806  for (int r=0; r<numRegs; r++) {
+
3807  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
+
3808  found = 0;
+
3809  break;
+
3810  }
+
3811  }
+
3812  if (found)
+
3813  break;
+
3814  }
+
3815 
+
3816  // compute the phase (unless overriden)
+
3817  qreal phase = 0;
+
3818  if (i < numOverrides)
+
3819  phase = overridePhases[i];
+
3820  else {
+
3821  // compute norm related phases
+
3822  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
+
3823  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
+
3824  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
3825  qreal norm = 0;
+
3826  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
3827  for (int r=0; r<numRegs; r++) {
+
3828  qreal dif = phaseInds[r*stride+offset] - params[2+r];
+
3829  norm += dif*dif;
+
3830  }
+
3831  }
+
3832  else
+
3833  for (int r=0; r<numRegs; r++)
+
3834  norm += phaseInds[r*stride+offset]*phaseInds[r*stride+offset];
+
3835  norm = sqrt(norm);
+
3836 
+
3837  if (phaseFuncName == NORM)
+
3838  phase = norm;
+
3839  else if (phaseFuncName == INVERSE_NORM)
+
3840  phase = (norm == 0.)? params[0] : 1/norm; // smallest non-zero norm is 1
+
3841  else if (phaseFuncName == SCALED_NORM)
+
3842  phase = params[0] * norm;
+
3843  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
+
3844  phase = (norm <= REAL_EPS)? params[1] : params[0] / norm; // unless shifted closer to zero
+
3845  }
+
3846  // compute product related phases
+
3847  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
+
3848  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
+
3849 
+
3850  qreal prod = 1;
+
3851  for (int r=0; r<numRegs; r++)
+
3852  prod *= phaseInds[r*stride+offset];
+
3853 
+
3854  if (phaseFuncName == PRODUCT)
+
3855  phase = prod;
+
3856  else if (phaseFuncName == INVERSE_PRODUCT)
+
3857  phase = (prod == 0.)? params[0] : 1/prod; // smallest non-zero prod is +- 1
+
3858  else if (phaseFuncName == SCALED_PRODUCT)
+
3859  phase = params[0] * prod;
+
3860  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
+
3861  phase = (prod == 0.)? params[1] : params[0] / prod;
+
3862  }
+
3863  // compute Euclidean distance related phases
+
3864  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
+
3865  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
+
3866  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
3867 
+
3868  qreal dist = 0;
+
3869  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
3870  for (int r=0; r<numRegs; r+=2) {
+
3871  qreal dif = (phaseInds[r*stride+offset] - phaseInds[(r+1)*stride+offset] - params[2+r/2]);
+
3872  dist += dif*dif;
+
3873  }
+
3874  }
+
3875  else
+
3876  for (int r=0; r<numRegs; r+=2) {
+
3877  qreal dif = (phaseInds[(r+1)*stride+offset] - phaseInds[r*stride+offset]);
+
3878  dist += dif*dif;
+
3879  }
+
3880  dist = sqrt(dist);
+
3881 
+
3882  if (phaseFuncName == DISTANCE)
+
3883  phase = dist;
+
3884  else if (phaseFuncName == INVERSE_DISTANCE)
+
3885  phase = (dist == 0.)? params[0] : 1/dist; // smallest non-zero dist is 1
+
3886  else if (phaseFuncName == SCALED_DISTANCE)
+
3887  phase = params[0] * dist;
+
3888  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
+
3889  phase = (dist <= REAL_EPS)? params[1] : params[0] / dist; // unless shifted closer
+
3890  }
+
3891  }
+
3892 
+
3893 
+
3894  // negate phase to conjugate operator
+
3895  if (conj)
+
3896  phase *= -1;
+
3897 
+
3898  // modify amp to amp * exp(i phase)
+
3899  qreal c = cos(phase);
+
3900  qreal s = sin(phase);
+
3901  qreal re = qureg.deviceStateVec.real[index];
+
3902  qreal im = qureg.deviceStateVec.imag[index];
+
3903 
+
3904  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
3905  qureg.deviceStateVec.real[index] = re*c - im*s;
+
3906  qureg.deviceStateVec.imag[index] = re*s + im*c;
+
3907 }

References Qureg::deviceStateVec, DISTANCE, extractBit(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, NORM, Qureg::numAmpsPerChunk, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, TWOS_COMPLEMENT, and UNSIGNED.

@@ -4931,40 +4931,40 @@

-

Definition at line 3574 of file QuEST_gpu.cu.

-
3579  {
-
3580  // allocate device space for global list of {qubits}, {coeffs}, {exponents}, {overrideInds} and {overridePhases}
-
3581  int* d_qubits; size_t mem_qubits = numQubits * sizeof *d_qubits;
-
3582  qreal* d_coeffs; size_t mem_terms = numTerms * sizeof *d_coeffs;
-
3583  qreal* d_exponents;
-
3584  long long int* d_overrideInds; size_t mem_inds = numOverrides * sizeof *d_overrideInds;
-
3585  qreal* d_overridePhases; size_t mem_phas = numOverrides * sizeof *d_overridePhases;
-
3586  cudaMalloc(&d_qubits, mem_qubits); cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
3587  cudaMalloc(&d_coeffs, mem_terms); cudaMemcpy(d_coeffs, coeffs, mem_terms, cudaMemcpyHostToDevice);
-
3588  cudaMalloc(&d_exponents, mem_terms); cudaMemcpy(d_exponents, exponents, mem_terms, cudaMemcpyHostToDevice);
-
3589  cudaMalloc(&d_overrideInds, mem_inds); cudaMemcpy(d_overrideInds, overrideInds, mem_inds, cudaMemcpyHostToDevice);
-
3590  cudaMalloc(&d_overridePhases,mem_phas); cudaMemcpy(d_overridePhases, overridePhases, mem_phas, cudaMemcpyHostToDevice);
-
3591 
-
3592  // call kernel
-
3593  int threadsPerCUDABlock = 128;
-
3594  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
-
3595  statevec_applyPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
3596  qureg, d_qubits, numQubits, encoding,
-
3597  d_coeffs, d_exponents, numTerms,
-
3598  d_overrideInds, d_overridePhases, numOverrides,
-
3599  conj);
-
3600 
-
3601  // cleanup device memory
-
3602  cudaFree(d_qubits);
-
3603  cudaFree(d_coeffs);
-
3604  cudaFree(d_exponents);
-
3605  cudaFree(d_overrideInds);
-
3606  cudaFree(d_overridePhases);
-
3607 }
+

Definition at line 3576 of file QuEST_gpu.cu.

+
3581  {
+
3582  // allocate device space for global list of {qubits}, {coeffs}, {exponents}, {overrideInds} and {overridePhases}
+
3583  int* d_qubits; size_t mem_qubits = numQubits * sizeof *d_qubits;
+
3584  qreal* d_coeffs; size_t mem_terms = numTerms * sizeof *d_coeffs;
+
3585  qreal* d_exponents;
+
3586  long long int* d_overrideInds; size_t mem_inds = numOverrides * sizeof *d_overrideInds;
+
3587  qreal* d_overridePhases; size_t mem_phas = numOverrides * sizeof *d_overridePhases;
+
3588  cudaMalloc(&d_qubits, mem_qubits); cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
3589  cudaMalloc(&d_coeffs, mem_terms); cudaMemcpy(d_coeffs, coeffs, mem_terms, cudaMemcpyHostToDevice);
+
3590  cudaMalloc(&d_exponents, mem_terms); cudaMemcpy(d_exponents, exponents, mem_terms, cudaMemcpyHostToDevice);
+
3591  cudaMalloc(&d_overrideInds, mem_inds); cudaMemcpy(d_overrideInds, overrideInds, mem_inds, cudaMemcpyHostToDevice);
+
3592  cudaMalloc(&d_overridePhases,mem_phas); cudaMemcpy(d_overridePhases, overridePhases, mem_phas, cudaMemcpyHostToDevice);
+
3593 
+
3594  // call kernel
+
3595  int threadsPerCUDABlock = 128;
+
3596  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
+
3597  statevec_applyPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
3598  qureg, d_qubits, numQubits, encoding,
+
3599  d_coeffs, d_exponents, numTerms,
+
3600  d_overrideInds, d_overridePhases, numOverrides,
+
3601  conj);
+
3602 
+
3603  // cleanup device memory
+
3604  cudaFree(d_qubits);
+
3605  cudaFree(d_coeffs);
+
3606  cudaFree(d_exponents);
+
3607  cudaFree(d_overrideInds);
+
3608  cudaFree(d_overridePhases);
+
3609 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -5048,55 +5048,55 @@

-

Definition at line 3520 of file QuEST_gpu.cu.

-
3525  {
-
3526  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3527  if (index>=qureg.numAmpsPerChunk) return;
-
3528 
-
3529  // determine global amplitude index (non-distributed, so it's just local index)
-
3530  long long int globalAmpInd = index;
-
3531 
-
3532  // determine phase index of {qubits}
-
3533  long long int phaseInd = 0LL;
-
3534  if (encoding == UNSIGNED) {
-
3535  for (int q=0; q<numQubits; q++)
-
3536  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
3537  }
-
3538  else if (encoding == TWOS_COMPLEMENT) {
-
3539  for (int q=0; q<numQubits-1; q++) // use final qubit to indicate sign
-
3540  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
3541  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
-
3542  phaseInd -= (1LL << (numQubits-1));
-
3543  }
-
3544 
-
3545  // determine if this phase index has an overriden value (i < numOverrides)
-
3546  int i;
-
3547  for (i=0; i<numOverrides; i++)
-
3548  if (phaseInd == overrideInds[i])
-
3549  break;
-
3550 
-
3551  // determine phase from {coeffs}, {exponents} (unless overriden)
-
3552  qreal phase = 0;
-
3553  if (i < numOverrides)
-
3554  phase = overridePhases[i];
-
3555  else
-
3556  for (int t=0; t<numTerms; t++)
-
3557  phase += coeffs[t] * pow(phaseInd, exponents[t]);
-
3558 
-
3559  // negate phase to conjugate operator
-
3560  if (conj)
-
3561  phase *= -1;
-
3562 
-
3563  // modify amp to amp * exp(i phase)
-
3564  qreal c = cos(phase);
-
3565  qreal s = sin(phase);
-
3566  qreal re = qureg.deviceStateVec.real[index];
-
3567  qreal im = qureg.deviceStateVec.imag[index];
-
3568 
-
3569  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
3570  qureg.deviceStateVec.real[index] = re*c - im*s;
-
3571  qureg.deviceStateVec.imag[index] = re*s + im*c;
-
3572 }
+

Definition at line 3522 of file QuEST_gpu.cu.

+
3527  {
+
3528  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3529  if (index>=qureg.numAmpsPerChunk) return;
+
3530 
+
3531  // determine global amplitude index (non-distributed, so it's just local index)
+
3532  long long int globalAmpInd = index;
+
3533 
+
3534  // determine phase index of {qubits}
+
3535  long long int phaseInd = 0LL;
+
3536  if (encoding == UNSIGNED) {
+
3537  for (int q=0; q<numQubits; q++)
+
3538  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
3539  }
+
3540  else if (encoding == TWOS_COMPLEMENT) {
+
3541  for (int q=0; q<numQubits-1; q++) // use final qubit to indicate sign
+
3542  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
3543  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
+
3544  phaseInd -= (1LL << (numQubits-1));
+
3545  }
+
3546 
+
3547  // determine if this phase index has an overriden value (i < numOverrides)
+
3548  int i;
+
3549  for (i=0; i<numOverrides; i++)
+
3550  if (phaseInd == overrideInds[i])
+
3551  break;
+
3552 
+
3553  // determine phase from {coeffs}, {exponents} (unless overriden)
+
3554  qreal phase = 0;
+
3555  if (i < numOverrides)
+
3556  phase = overridePhases[i];
+
3557  else
+
3558  for (int t=0; t<numTerms; t++)
+
3559  phase += coeffs[t] * pow(phaseInd, exponents[t]);
+
3560 
+
3561  // negate phase to conjugate operator
+
3562  if (conj)
+
3563  phase *= -1;
+
3564 
+
3565  // modify amp to amp * exp(i phase)
+
3566  qreal c = cos(phase);
+
3567  qreal s = sin(phase);
+
3568  qreal re = qureg.deviceStateVec.real[index];
+
3569  qreal im = qureg.deviceStateVec.imag[index];
+
3570 
+
3571  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
3572  qureg.deviceStateVec.real[index] = re*c - im*s;
+
3573  qureg.deviceStateVec.imag[index] = re*s + im*c;
+
3574 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, qreal, TWOS_COMPLEMENT, and UNSIGNED.

@@ -5128,101 +5128,101 @@

-

Definition at line 3274 of file QuEST_gpu.cu.

-
3274  {
-
3275 
-
3276  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3277  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3278  */
-
3279 
-
3280  qreal expecReal, expecImag;
-
3281 
-
3282  int getRealComp;
-
3283  long long int numValuesToReduce;
-
3284  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3285  int maxReducedPerLevel;
-
3286  int firstTime;
-
3287 
-
3288  // compute real component of inner product
-
3289  getRealComp = 1;
-
3290  numValuesToReduce = qureg.numAmpsPerChunk;
-
3291  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3292  firstTime = 1;
-
3293  while (numValuesToReduce > 1) {
-
3294  if (numValuesToReduce < maxReducedPerLevel) {
-
3295  valuesPerCUDABlock = numValuesToReduce;
-
3296  numCUDABlocks = 1;
-
3297  }
-
3298  else {
-
3299  valuesPerCUDABlock = maxReducedPerLevel;
-
3300  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3301  }
-
3302  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3303  if (firstTime) {
-
3304  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3305  getRealComp,
-
3306  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3307  op.deviceOperator.real, op.deviceOperator.imag,
-
3308  numValuesToReduce,
-
3309  qureg.firstLevelReduction);
-
3310  firstTime = 0;
-
3311  } else {
-
3312  cudaDeviceSynchronize();
-
3313  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3314  qureg.firstLevelReduction,
-
3315  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3316  cudaDeviceSynchronize();
- -
3318  }
-
3319  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3320  }
-
3321  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3322 
-
3323  // compute imag component of inner product
-
3324  getRealComp = 0;
-
3325  numValuesToReduce = qureg.numAmpsPerChunk;
-
3326  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3327  firstTime = 1;
-
3328  while (numValuesToReduce > 1) {
-
3329  if (numValuesToReduce < maxReducedPerLevel) {
-
3330  valuesPerCUDABlock = numValuesToReduce;
-
3331  numCUDABlocks = 1;
-
3332  }
-
3333  else {
-
3334  valuesPerCUDABlock = maxReducedPerLevel;
-
3335  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3336  }
-
3337  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3338  if (firstTime) {
-
3339  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3340  getRealComp,
-
3341  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3342  op.deviceOperator.real, op.deviceOperator.imag,
-
3343  numValuesToReduce,
-
3344  qureg.firstLevelReduction);
-
3345  firstTime = 0;
-
3346  } else {
-
3347  cudaDeviceSynchronize();
-
3348  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3349  qureg.firstLevelReduction,
-
3350  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3351  cudaDeviceSynchronize();
- -
3353  }
-
3354  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3355  }
-
3356  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3357 
-
3358  // return complex
-
3359  Complex expecVal;
-
3360  expecVal.real = expecReal;
-
3361  expecVal.imag = expecImag;
-
3362  return expecVal;
-
3363 }
-
-

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcExpecDiagonalOp().

+

Definition at line 3276 of file QuEST_gpu.cu.

+
3276  {
+
3277 
+
3278  /* @TODO: remove all this reduction boilerplate from QuEST GPU
+
3279  * (e.g. a func which accepts a pointer to do every-value reduction?)
+
3280  */
+
3281 
+
3282  qreal expecReal, expecImag;
+
3283 
+
3284  int getRealComp;
+
3285  long long int numValuesToReduce;
+
3286  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
3287  int maxReducedPerLevel;
+
3288  int firstTime;
+
3289 
+
3290  // compute real component of inner product
+
3291  getRealComp = 1;
+
3292  numValuesToReduce = qureg.numAmpsPerChunk;
+
3293  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3294  firstTime = 1;
+
3295  while (numValuesToReduce > 1) {
+
3296  if (numValuesToReduce < maxReducedPerLevel) {
+
3297  valuesPerCUDABlock = numValuesToReduce;
+
3298  numCUDABlocks = 1;
+
3299  }
+
3300  else {
+
3301  valuesPerCUDABlock = maxReducedPerLevel;
+
3302  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3303  }
+
3304  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3305  if (firstTime) {
+
3306  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3307  getRealComp,
+
3308  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3309  op.deviceOperator.real, op.deviceOperator.imag,
+
3310  numValuesToReduce,
+
3311  qureg.firstLevelReduction);
+
3312  firstTime = 0;
+
3313  } else {
+
3314  cudaDeviceSynchronize();
+
3315  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3316  qureg.firstLevelReduction,
+
3317  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3318  cudaDeviceSynchronize();
+ +
3320  }
+
3321  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3322  }
+
3323  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3324 
+
3325  // compute imag component of inner product
+
3326  getRealComp = 0;
+
3327  numValuesToReduce = qureg.numAmpsPerChunk;
+
3328  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3329  firstTime = 1;
+
3330  while (numValuesToReduce > 1) {
+
3331  if (numValuesToReduce < maxReducedPerLevel) {
+
3332  valuesPerCUDABlock = numValuesToReduce;
+
3333  numCUDABlocks = 1;
+
3334  }
+
3335  else {
+
3336  valuesPerCUDABlock = maxReducedPerLevel;
+
3337  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3338  }
+
3339  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3340  if (firstTime) {
+
3341  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3342  getRealComp,
+
3343  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3344  op.deviceOperator.real, op.deviceOperator.imag,
+
3345  numValuesToReduce,
+
3346  qureg.firstLevelReduction);
+
3347  firstTime = 0;
+
3348  } else {
+
3349  cudaDeviceSynchronize();
+
3350  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3351  qureg.firstLevelReduction,
+
3352  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3353  cudaDeviceSynchronize();
+ +
3355  }
+
3356  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3357  }
+
3358  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3359 
+
3360  // return complex
+
3361  Complex expecVal;
+
3362  expecVal.real = expecReal;
+
3363  expecVal.imag = expecImag;
+
3364  return expecVal;
+
3365 }
+
+

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcExpecDiagonalOp().

@@ -5284,31 +5284,31 @@

Definition at line 3247 of file QuEST_gpu.cu.

-
3251 {
-
3252  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3253  if (index >= numTermsToSum) return;
-
3254 
-
3255  qreal vecAbs = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+

Definition at line 3249 of file QuEST_gpu.cu.

+
3253 {
+
3254  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3255  if (index >= numTermsToSum) return;
3256 
-
3257  // choose whether to calculate the real or imaginary term of the expec term
-
3258  qreal expecVal;
-
3259  if (getRealComp)
-
3260  expecVal = vecAbs * opReal[index];
-
3261  else
-
3262  expecVal = vecAbs * opImag[index];
-
3263 
-
3264  // array of each thread's collected sum term, to be summed
-
3265  extern __shared__ qreal tempReductionArray[];
-
3266  tempReductionArray[threadIdx.x] = expecVal;
-
3267  __syncthreads();
-
3268 
-
3269  // every second thread reduces
-
3270  if (threadIdx.x<blockDim.x/2)
-
3271  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3272 }
-
-

References qreal, and reduceBlock().

+
3257  qreal vecAbs = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+
3258 
+
3259  // choose whether to calculate the real or imaginary term of the expec term
+
3260  qreal expecVal;
+
3261  if (getRealComp)
+
3262  expecVal = vecAbs * opReal[index];
+
3263  else
+
3264  expecVal = vecAbs * opImag[index];
+
3265 
+
3266  // array of each thread's collected sum term, to be summed
+
3267  extern __shared__ qreal tempReductionArray[];
+
3268  tempReductionArray[threadIdx.x] = expecVal;
+
3269  __syncthreads();
+
3270 
+
3271  // every second thread reduces
+
3272  if (threadIdx.x<blockDim.x/2)
+
3273  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
3274 }
+
+

References qreal, and reduceBlock().

@@ -5341,97 +5341,97 @@

Todo:
could even do the kernel twice, storing real in bra.reduc and imag in ket.reduc?
-

Definition at line 2391 of file QuEST_gpu.cu.

-
2391  {
-
2392 
-
2393  qreal innerProdReal, innerProdImag;
+

Definition at line 2393 of file QuEST_gpu.cu.

+
2393  {
2394 
-
2395  int getRealComp;
-
2396  long long int numValuesToReduce;
-
2397  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2398  int maxReducedPerLevel;
-
2399  int firstTime;
-
2400 
-
2401  // compute real component of inner product
-
2402  getRealComp = 1;
-
2403  numValuesToReduce = bra.numAmpsPerChunk;
-
2404  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2405  firstTime = 1;
-
2406  while (numValuesToReduce > 1) {
-
2407  if (numValuesToReduce < maxReducedPerLevel) {
-
2408  valuesPerCUDABlock = numValuesToReduce;
-
2409  numCUDABlocks = 1;
-
2410  }
-
2411  else {
-
2412  valuesPerCUDABlock = maxReducedPerLevel;
-
2413  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2414  }
-
2415  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2416  if (firstTime) {
-
2417  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2418  getRealComp,
-
2419  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2420  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2421  numValuesToReduce,
-
2422  bra.firstLevelReduction);
-
2423  firstTime = 0;
-
2424  } else {
-
2425  cudaDeviceSynchronize();
-
2426  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2427  bra.firstLevelReduction,
-
2428  bra.secondLevelReduction, valuesPerCUDABlock);
-
2429  cudaDeviceSynchronize();
- -
2431  }
-
2432  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2433  }
-
2434  cudaMemcpy(&innerProdReal, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2435 
-
2436  // compute imag component of inner product
-
2437  getRealComp = 0;
-
2438  numValuesToReduce = bra.numAmpsPerChunk;
-
2439  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2440  firstTime = 1;
-
2441  while (numValuesToReduce > 1) {
-
2442  if (numValuesToReduce < maxReducedPerLevel) {
-
2443  valuesPerCUDABlock = numValuesToReduce;
-
2444  numCUDABlocks = 1;
-
2445  }
-
2446  else {
-
2447  valuesPerCUDABlock = maxReducedPerLevel;
-
2448  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2449  }
-
2450  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2451  if (firstTime) {
-
2452  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2453  getRealComp,
-
2454  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2455  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2456  numValuesToReduce,
-
2457  bra.firstLevelReduction);
-
2458  firstTime = 0;
-
2459  } else {
-
2460  cudaDeviceSynchronize();
-
2461  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2462  bra.firstLevelReduction,
-
2463  bra.secondLevelReduction, valuesPerCUDABlock);
-
2464  cudaDeviceSynchronize();
- -
2466  }
-
2467  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2468  }
-
2469  cudaMemcpy(&innerProdImag, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2470 
-
2471  // return complex
-
2472  Complex innerProd;
-
2473  innerProd.real = innerProdReal;
-
2474  innerProd.imag = innerProdImag;
-
2475  return innerProd;
-
2476 }
-
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

- -

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

+
2395  qreal innerProdReal, innerProdImag;
+
2396 
+
2397  int getRealComp;
+
2398  long long int numValuesToReduce;
+
2399  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2400  int maxReducedPerLevel;
+
2401  int firstTime;
+
2402 
+
2403  // compute real component of inner product
+
2404  getRealComp = 1;
+
2405  numValuesToReduce = bra.numAmpsPerChunk;
+
2406  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2407  firstTime = 1;
+
2408  while (numValuesToReduce > 1) {
+
2409  if (numValuesToReduce < maxReducedPerLevel) {
+
2410  valuesPerCUDABlock = numValuesToReduce;
+
2411  numCUDABlocks = 1;
+
2412  }
+
2413  else {
+
2414  valuesPerCUDABlock = maxReducedPerLevel;
+
2415  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2416  }
+
2417  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2418  if (firstTime) {
+
2419  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2420  getRealComp,
+
2421  bra.deviceStateVec.real, bra.deviceStateVec.imag,
+
2422  ket.deviceStateVec.real, ket.deviceStateVec.imag,
+
2423  numValuesToReduce,
+
2424  bra.firstLevelReduction);
+
2425  firstTime = 0;
+
2426  } else {
+
2427  cudaDeviceSynchronize();
+
2428  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2429  bra.firstLevelReduction,
+
2430  bra.secondLevelReduction, valuesPerCUDABlock);
+
2431  cudaDeviceSynchronize();
+ +
2433  }
+
2434  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2435  }
+
2436  cudaMemcpy(&innerProdReal, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2437 
+
2438  // compute imag component of inner product
+
2439  getRealComp = 0;
+
2440  numValuesToReduce = bra.numAmpsPerChunk;
+
2441  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2442  firstTime = 1;
+
2443  while (numValuesToReduce > 1) {
+
2444  if (numValuesToReduce < maxReducedPerLevel) {
+
2445  valuesPerCUDABlock = numValuesToReduce;
+
2446  numCUDABlocks = 1;
+
2447  }
+
2448  else {
+
2449  valuesPerCUDABlock = maxReducedPerLevel;
+
2450  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2451  }
+
2452  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2453  if (firstTime) {
+
2454  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2455  getRealComp,
+
2456  bra.deviceStateVec.real, bra.deviceStateVec.imag,
+
2457  ket.deviceStateVec.real, ket.deviceStateVec.imag,
+
2458  numValuesToReduce,
+
2459  bra.firstLevelReduction);
+
2460  firstTime = 0;
+
2461  } else {
+
2462  cudaDeviceSynchronize();
+
2463  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2464  bra.firstLevelReduction,
+
2465  bra.secondLevelReduction, valuesPerCUDABlock);
+
2466  cudaDeviceSynchronize();
+ +
2468  }
+
2469  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2470  }
+
2471  cudaMemcpy(&innerProdImag, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2472 
+
2473  // return complex
+
2474  Complex innerProd;
+
2475  innerProd.real = innerProdReal;
+
2476  innerProd.imag = innerProdImag;
+
2477  return innerProd;
+
2478 }
+
+

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+ +

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

@@ -5493,29 +5493,29 @@

Definition at line 2361 of file QuEST_gpu.cu.

-
2365 {
-
2366  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2367  if (index >= numTermsToSum) return;
-
2368 
-
2369  // choose whether to calculate the real or imaginary term of the inner product
-
2370  qreal innerProdTerm;
-
2371  if (getRealComp)
-
2372  innerProdTerm = vecReal1[index]*vecReal2[index] + vecImag1[index]*vecImag2[index];
-
2373  else
-
2374  innerProdTerm = vecReal1[index]*vecImag2[index] - vecImag1[index]*vecReal2[index];
-
2375 
-
2376  // array of each thread's collected sum term, to be summed
-
2377  extern __shared__ qreal tempReductionArray[];
-
2378  tempReductionArray[threadIdx.x] = innerProdTerm;
-
2379  __syncthreads();
-
2380 
-
2381  // every second thread reduces
-
2382  if (threadIdx.x<blockDim.x/2)
-
2383  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2384 }
-
-

References qreal, and reduceBlock().

+

Definition at line 2363 of file QuEST_gpu.cu.

+
2367 {
+
2368  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2369  if (index >= numTermsToSum) return;
+
2370 
+
2371  // choose whether to calculate the real or imaginary term of the inner product
+
2372  qreal innerProdTerm;
+
2373  if (getRealComp)
+
2374  innerProdTerm = vecReal1[index]*vecReal2[index] + vecImag1[index]*vecImag2[index];
+
2375  else
+
2376  innerProdTerm = vecReal1[index]*vecImag2[index] - vecImag1[index]*vecReal2[index];
+
2377 
+
2378  // array of each thread's collected sum term, to be summed
+
2379  extern __shared__ qreal tempReductionArray[];
+
2380  tempReductionArray[threadIdx.x] = innerProdTerm;
+
2381  __syncthreads();
+
2382 
+
2383  // every second thread reduces
+
2384  if (threadIdx.x<blockDim.x/2)
+
2385  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2386 }
+
+

References qreal, and reduceBlock().

@@ -5557,41 +5557,41 @@

-

Definition at line 2205 of file QuEST_gpu.cu.

-
2205  {
-
2206 
-
2207  // copy qubits to GPU memory
-
2208  int* d_qubits;
-
2209  size_t mem_qubits = numQubits * sizeof *d_qubits;
-
2210  cudaMalloc(&d_qubits, mem_qubits);
-
2211  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
2212 
-
2213  // create one thread for every amplitude
-
2214  int numThreadsPerBlock = 128;
-
2215  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
-
2216 
-
2217  // create global GPU array for outcomeProbs
-
2218  qreal* d_outcomeProbs;
-
2219  long long int numOutcomes = (1LL << numQubits);
-
2220  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
-
2221  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
-
2222  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
-
2223 
-
2224  // populate per-block subarrays
-
2225  statevec_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
-
2226  d_outcomeProbs, qureg, d_qubits, numQubits);
-
2227 
-
2228  // copy outcomeProbs from GPU memory
-
2229  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
-
2230 
-
2231  // free GPU memory
-
2232  cudaFree(d_qubits);
-
2233  cudaFree(d_outcomeProbs);
-
2234 }
+

Definition at line 2207 of file QuEST_gpu.cu.

+
2207  {
+
2208 
+
2209  // copy qubits to GPU memory
+
2210  int* d_qubits;
+
2211  size_t mem_qubits = numQubits * sizeof *d_qubits;
+
2212  cudaMalloc(&d_qubits, mem_qubits);
+
2213  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
2214 
+
2215  // create one thread for every amplitude
+
2216  int numThreadsPerBlock = 128;
+
2217  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
+
2218 
+
2219  // create global GPU array for outcomeProbs
+
2220  qreal* d_outcomeProbs;
+
2221  long long int numOutcomes = (1LL << numQubits);
+
2222  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
+
2223  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
+
2224  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
+
2225 
+
2226  // populate per-block subarrays
+
2227  statevec_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
+
2228  d_outcomeProbs, qureg, d_qubits, numQubits);
+
2229 
+
2230  // copy outcomeProbs from GPU memory
+
2231  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
+
2232 
+
2233  // free GPU memory
+
2234  cudaFree(d_qubits);
+
2235  cudaFree(d_outcomeProbs);
+
2236 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by calcProbOfAllOutcomes().

+

Referenced by calcProbOfAllOutcomes().

@@ -5633,25 +5633,25 @@

-

Definition at line 2184 of file QuEST_gpu.cu.

-
2186  {
-
2187  // each thread handles one amplitude (all amplitudes are involved)
-
2188  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2189  if (ampInd >= qureg.numAmpsTotal) return;
-
2190 
-
2191  qreal prob = (
-
2192  qureg.deviceStateVec.real[ampInd]*qureg.deviceStateVec.real[ampInd] +
-
2193  qureg.deviceStateVec.imag[ampInd]*qureg.deviceStateVec.imag[ampInd]);
-
2194 
-
2195  // each amplitude contributes to one outcome
-
2196  long long int outcomeInd = 0;
-
2197  for (int q=0; q<numQubits; q++)
-
2198  outcomeInd += extractBit(qubits[q], ampInd) * (1LL << q);
-
2199 
-
2200  // each thread atomically writes directly to the global output.
-
2201  // this beat block-heirarchal atomic reductions in both global and shared memory!
-
2202  atomicAdd(&outcomeProbs[outcomeInd], prob);
-
2203 }
+

Definition at line 2186 of file QuEST_gpu.cu.

+
2188  {
+
2189  // each thread handles one amplitude (all amplitudes are involved)
+
2190  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2191  if (ampInd >= qureg.numAmpsTotal) return;
+
2192 
+
2193  qreal prob = (
+
2194  qureg.deviceStateVec.real[ampInd]*qureg.deviceStateVec.real[ampInd] +
+
2195  qureg.deviceStateVec.imag[ampInd]*qureg.deviceStateVec.imag[ampInd]);
+
2196 
+
2197  // each amplitude contributes to one outcome
+
2198  long long int outcomeInd = 0;
+
2199  for (int q=0; q<numQubits; q++)
+
2200  outcomeInd += extractBit(qubits[q], ampInd) * (1LL << q);
+
2201 
+
2202  // each thread atomically writes directly to the global output.
+
2203  // this beat block-heirarchal atomic reductions in both global and shared memory!
+
2204  atomicAdd(&outcomeProbs[outcomeInd], prob);
+
2205 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsTotal, and qreal.

@@ -5689,17 +5689,17 @@

-

Definition at line 2148 of file QuEST_gpu.cu.

-
2149 {
-
2150  qreal outcomeProb = statevec_findProbabilityOfZero(qureg, measureQubit);
-
2151  if (outcome==1)
-
2152  outcomeProb = 1.0 - outcomeProb;
-
2153  return outcomeProb;
-
2154 }
+

Definition at line 2150 of file QuEST_gpu.cu.

+
2151 {
+
2152  qreal outcomeProb = statevec_findProbabilityOfZero(qureg, measureQubit);
+
2153  if (outcome==1)
+
2154  outcomeProb = 1.0 - outcomeProb;
+
2155  return outcomeProb;
+
2156 }
-

References qreal, and statevec_findProbabilityOfZero().

+

References qreal, and statevec_findProbabilityOfZero().

-

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

+

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

@@ -5719,42 +5719,42 @@

-

Definition at line 1653 of file QuEST_gpu.cu.

-
1653  {
-
1654  /* IJB - implemented using Kahan summation for greater accuracy at a slight floating
-
1655  point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
-
1656  /* Don't change the bracketing in this routine! */
-
1657  qreal pTotal=0;
-
1658  qreal y, t, c;
-
1659  long long int index;
-
1660  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
1661 
-
1662  copyStateFromGPU(qureg);
+

Definition at line 1655 of file QuEST_gpu.cu.

+
1655  {
+
1656  /* IJB - implemented using Kahan summation for greater accuracy at a slight floating
+
1657  point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
+
1658  /* Don't change the bracketing in this routine! */
+
1659  qreal pTotal=0;
+
1660  qreal y, t, c;
+
1661  long long int index;
+
1662  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
1663 
-
1664  c = 0.0;
-
1665  for (index=0; index<numAmpsPerRank; index++){
-
1666  /* Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan */
-
1667  // pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index];
-
1668  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
1669  t = pTotal + y;
-
1670  c = ( t - pTotal ) - y;
-
1671  pTotal = t;
-
1672 
-
1673  /* Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan */
-
1674  //pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index];
-
1675  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
1676  t = pTotal + y;
-
1677  c = ( t - pTotal ) - y;
-
1678  pTotal = t;
-
1679 
-
1680 
-
1681  }
-
1682  return pTotal;
-
1683 }
-
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

- -

Referenced by calcTotalProb().

+
1664  copyStateFromGPU(qureg);
+
1665 
+
1666  c = 0.0;
+
1667  for (index=0; index<numAmpsPerRank; index++){
+
1668  /* Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan */
+
1669  // pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index];
+
1670  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
+
1671  t = pTotal + y;
+
1672  c = ( t - pTotal ) - y;
+
1673  pTotal = t;
+
1674 
+
1675  /* Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan */
+
1676  //pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index];
+
1677  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
+
1678  t = pTotal + y;
+
1679  c = ( t - pTotal ) - y;
+
1680  pTotal = t;
+
1681 
+
1682 
+
1683  }
+
1684  return pTotal;
+
1685 }
+
+

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+ +

Referenced by calcTotalProb().

@@ -5805,7 +5805,7 @@

References Qureg::deviceStateVec, and Qureg::numAmpsPerChunk.

-

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

+

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

@@ -5847,17 +5847,17 @@

-

Definition at line 2768 of file QuEST_gpu.cu.

-
2769 {
-
2770  int threadsPerCUDABlock, CUDABlocks;
-
2771  threadsPerCUDABlock = 128;
-
2772  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
2773  statevec_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, measureQubit, outcome, outcomeProb);
-
2774 }
+

Definition at line 2770 of file QuEST_gpu.cu.

+
2771 {
+
2772  int threadsPerCUDABlock, CUDABlocks;
+
2773  threadsPerCUDABlock = 128;
+
2774  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
2775  statevec_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, measureQubit, outcome, outcomeProb);
+
2776 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by collapseToOutcome(), and statevec_measureWithStats().

+

Referenced by applyProjector(), collapseToOutcome(), and statevec_measureWithStats().

@@ -5899,58 +5899,58 @@

-

Definition at line 2711 of file QuEST_gpu.cu.

-
2712 {
-
2713  // ----- sizes
-
2714  long long int sizeBlock, // size of blocks
-
2715  sizeHalfBlock; // size of blocks halved
-
2716  // ----- indices
-
2717  long long int thisBlock, // current block
-
2718  index; // current index for first half block
-
2719  // ----- measured probability
-
2720  qreal renorm; // probability (returned) value
-
2721  // ----- temp variables
-
2722  long long int thisTask; // task based approach for expose loop with small granularity
-
2723  // (good for shared memory parallelism)
-
2724  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2725 
-
2726  // ---------------------------------------------------------------- //
-
2727  // dimensions //
+

Definition at line 2713 of file QuEST_gpu.cu.

+
2714 {
+
2715  // ----- sizes
+
2716  long long int sizeBlock, // size of blocks
+
2717  sizeHalfBlock; // size of blocks halved
+
2718  // ----- indices
+
2719  long long int thisBlock, // current block
+
2720  index; // current index for first half block
+
2721  // ----- measured probability
+
2722  qreal renorm; // probability (returned) value
+
2723  // ----- temp variables
+
2724  long long int thisTask; // task based approach for expose loop with small granularity
+
2725  // (good for shared memory parallelism)
+
2726  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2727 
2728  // ---------------------------------------------------------------- //
-
2729  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
2730  // and then the number to skip
-
2731  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
2732 
-
2733  // ---------------------------------------------------------------- //
-
2734  // find probability //
+
2729  // dimensions //
+
2730  // ---------------------------------------------------------------- //
+
2731  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
2732  // and then the number to skip
+
2733  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
2734 
2735  // ---------------------------------------------------------------- //
-
2736 
-
2737  //
-
2738  // --- task-based shared-memory parallel implementation
+
2736  // find probability //
+
2737  // ---------------------------------------------------------------- //
+
2738 
2739  //
-
2740  renorm=1/sqrt(totalProbability);
-
2741  qreal *stateVecReal = qureg.deviceStateVec.real;
-
2742  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
2743 
-
2744  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2745  if (thisTask>=numTasks) return;
-
2746  thisBlock = thisTask / sizeHalfBlock;
-
2747  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2748 
-
2749  if (outcome==0){
-
2750  stateVecReal[index]=stateVecReal[index]*renorm;
-
2751  stateVecImag[index]=stateVecImag[index]*renorm;
-
2752 
-
2753  stateVecReal[index+sizeHalfBlock]=0;
-
2754  stateVecImag[index+sizeHalfBlock]=0;
-
2755  } else if (outcome==1){
-
2756  stateVecReal[index]=0;
-
2757  stateVecImag[index]=0;
-
2758 
-
2759  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
2760  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
2761  }
-
2762 }
+
2740  // --- task-based shared-memory parallel implementation
+
2741  //
+
2742  renorm=1/sqrt(totalProbability);
+
2743  qreal *stateVecReal = qureg.deviceStateVec.real;
+
2744  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
2745 
+
2746  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
2747  if (thisTask>=numTasks) return;
+
2748  thisBlock = thisTask / sizeHalfBlock;
+
2749  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2750 
+
2751  if (outcome==0){
+
2752  stateVecReal[index]=stateVecReal[index]*renorm;
+
2753  stateVecImag[index]=stateVecImag[index]*renorm;
+
2754 
+
2755  stateVecReal[index+sizeHalfBlock]=0;
+
2756  stateVecImag[index+sizeHalfBlock]=0;
+
2757  } else if (outcome==1){
+
2758  stateVecReal[index]=0;
+
2759  stateVecImag[index]=0;
+
2760 
+
2761  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
+
2762  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
+
2763  }
+
2764 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -5994,17 +5994,17 @@

-

Definition at line 842 of file QuEST_gpu.cu.

-
843 {
-
844  int threadsPerCUDABlock, CUDABlocks;
-
845  threadsPerCUDABlock = 128;
-
846  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
847  statevec_compactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, alpha, beta);
-
848 }
+

Definition at line 844 of file QuEST_gpu.cu.

+
845 {
+
846  int threadsPerCUDABlock, CUDABlocks;
+
847  threadsPerCUDABlock = 128;
+
848  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
849  statevec_compactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, alpha, beta);
+
850 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by compactUnitary(), statevec_multiRotatePauli(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

+

Referenced by compactUnitary(), statevec_multiRotatePauli(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

@@ -6047,60 +6047,60 @@

fix – no necessary for GPU version

-

Definition at line 787 of file QuEST_gpu.cu.

-
787  {
-
788  // ----- sizes
-
789  long long int sizeBlock, // size of blocks
-
790  sizeHalfBlock; // size of blocks halved
-
791  // ----- indices
-
792  long long int thisBlock, // current block
-
793  indexUp,indexLo; // current index and corresponding index in lower half block
-
794 
-
795  // ----- temp variables
-
796  qreal stateRealUp,stateRealLo, // storage for previous state values
-
797  stateImagUp,stateImagLo; // (used in updates)
-
798  // ----- temp variables
-
799  long long int thisTask; // task based approach for expose loop with small granularity
-
800  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
801 
-
802  sizeHalfBlock = 1LL << rotQubit; // size of blocks halved
-
803  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
804 
-
805  // ---------------------------------------------------------------- //
-
806  // rotate //
+

Definition at line 789 of file QuEST_gpu.cu.

+
789  {
+
790  // ----- sizes
+
791  long long int sizeBlock, // size of blocks
+
792  sizeHalfBlock; // size of blocks halved
+
793  // ----- indices
+
794  long long int thisBlock, // current block
+
795  indexUp,indexLo; // current index and corresponding index in lower half block
+
796 
+
797  // ----- temp variables
+
798  qreal stateRealUp,stateRealLo, // storage for previous state values
+
799  stateImagUp,stateImagLo; // (used in updates)
+
800  // ----- temp variables
+
801  long long int thisTask; // task based approach for expose loop with small granularity
+
802  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
803 
+
804  sizeHalfBlock = 1LL << rotQubit; // size of blocks halved
+
805  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
806 
807  // ---------------------------------------------------------------- //
-
808 
-
810  qreal *stateVecReal = qureg.deviceStateVec.real;
-
811  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
812  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
813  qreal betaImag=beta.imag, betaReal=beta.real;
-
814 
-
815  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
816  if (thisTask>=numTasks) return;
-
817 
-
818  thisBlock = thisTask / sizeHalfBlock;
-
819  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
820  indexLo = indexUp + sizeHalfBlock;
-
821 
-
822  // store current state vector values in temp variables
-
823  stateRealUp = stateVecReal[indexUp];
-
824  stateImagUp = stateVecImag[indexUp];
-
825 
-
826  stateRealLo = stateVecReal[indexLo];
-
827  stateImagLo = stateVecImag[indexLo];
-
828 
-
829  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
830  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
831  - betaReal*stateRealLo - betaImag*stateImagLo;
-
832  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
833  - betaReal*stateImagLo + betaImag*stateRealLo;
-
834 
-
835  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
836  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
837  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
838  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
839  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
840 }
+
808  // rotate //
+
809  // ---------------------------------------------------------------- //
+
810 
+
812  qreal *stateVecReal = qureg.deviceStateVec.real;
+
813  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
814  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
815  qreal betaImag=beta.imag, betaReal=beta.real;
+
816 
+
817  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
818  if (thisTask>=numTasks) return;
+
819 
+
820  thisBlock = thisTask / sizeHalfBlock;
+
821  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
822  indexLo = indexUp + sizeHalfBlock;
+
823 
+
824  // store current state vector values in temp variables
+
825  stateRealUp = stateVecReal[indexUp];
+
826  stateImagUp = stateVecImag[indexUp];
+
827 
+
828  stateRealLo = stateVecReal[indexLo];
+
829  stateImagLo = stateVecImag[indexLo];
+
830 
+
831  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
832  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
833  - betaReal*stateRealLo - betaImag*stateImagLo;
+
834  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
835  - betaReal*stateImagLo + betaImag*stateRealLo;
+
836 
+
837  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
838  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
839  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
840  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
841  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
842 }

References Qureg::deviceStateVec, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

@@ -6138,28 +6138,28 @@

-

Definition at line 769 of file QuEST_gpu.cu.

-
769  {
-
770  qreal diff;
-
771  int chunkSize = mq1.numAmpsPerChunk;
-
772 
-
773  copyStateFromGPU(mq1);
-
774  copyStateFromGPU(mq2);
-
775 
-
776  for (int i=0; i<chunkSize; i++){
-
777  diff = mq1.stateVec.real[i] - mq2.stateVec.real[i];
-
778  if (diff<0) diff *= -1;
-
779  if (diff>precision) return 0;
-
780  diff = mq1.stateVec.imag[i] - mq2.stateVec.imag[i];
-
781  if (diff<0) diff *= -1;
-
782  if (diff>precision) return 0;
-
783  }
-
784  return 1;
-
785 }
+

Definition at line 771 of file QuEST_gpu.cu.

+
771  {
+
772  qreal diff;
+
773  int chunkSize = mq1.numAmpsPerChunk;
+
774 
+
775  copyStateFromGPU(mq1);
+
776  copyStateFromGPU(mq2);
+
777 
+
778  for (int i=0; i<chunkSize; i++){
+
779  diff = mq1.stateVec.real[i] - mq2.stateVec.real[i];
+
780  if (diff<0) diff *= -1;
+
781  if (diff>precision) return 0;
+
782  diff = mq1.stateVec.imag[i] - mq2.stateVec.imag[i];
+
783  if (diff<0) diff *= -1;
+
784  if (diff>precision) return 0;
+
785  }
+
786  return 1;
+
787 }
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by compareStates().

+

Referenced by compareStates().

@@ -6207,17 +6207,17 @@

-

Definition at line 909 of file QuEST_gpu.cu.

-
910 {
-
911  int threadsPerCUDABlock, CUDABlocks;
-
912  threadsPerCUDABlock = 128;
-
913  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
914  statevec_controlledCompactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, alpha, beta);
-
915 }
+

Definition at line 911 of file QuEST_gpu.cu.

+
912 {
+
913  int threadsPerCUDABlock, CUDABlocks;
+
914  threadsPerCUDABlock = 128;
+
915  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
916  statevec_controlledCompactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, alpha, beta);
+
917 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledCompactUnitary(), statevec_controlledRotateAroundAxis(), and statevec_controlledRotateAroundAxisConj().

+

Referenced by controlledCompactUnitary(), statevec_controlledRotateAroundAxis(), and statevec_controlledRotateAroundAxisConj().

@@ -6266,64 +6266,64 @@

fix – no necessary for GPU version

-

Definition at line 850 of file QuEST_gpu.cu.

-
850  {
-
851  // ----- sizes
-
852  long long int sizeBlock, // size of blocks
-
853  sizeHalfBlock; // size of blocks halved
-
854  // ----- indices
-
855  long long int thisBlock, // current block
-
856  indexUp,indexLo; // current index and corresponding index in lower half block
-
857 
-
858  // ----- temp variables
-
859  qreal stateRealUp,stateRealLo, // storage for previous state values
-
860  stateImagUp,stateImagLo; // (used in updates)
-
861  // ----- temp variables
-
862  long long int thisTask; // task based approach for expose loop with small granularity
-
863  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
864  int controlBit;
-
865 
-
866  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
867  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
868 
-
869  // ---------------------------------------------------------------- //
-
870  // rotate //
+

Definition at line 852 of file QuEST_gpu.cu.

+
852  {
+
853  // ----- sizes
+
854  long long int sizeBlock, // size of blocks
+
855  sizeHalfBlock; // size of blocks halved
+
856  // ----- indices
+
857  long long int thisBlock, // current block
+
858  indexUp,indexLo; // current index and corresponding index in lower half block
+
859 
+
860  // ----- temp variables
+
861  qreal stateRealUp,stateRealLo, // storage for previous state values
+
862  stateImagUp,stateImagLo; // (used in updates)
+
863  // ----- temp variables
+
864  long long int thisTask; // task based approach for expose loop with small granularity
+
865  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
866  int controlBit;
+
867 
+
868  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
869  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
870 
871  // ---------------------------------------------------------------- //
-
872 
-
874  qreal *stateVecReal = qureg.deviceStateVec.real;
-
875  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
876  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
877  qreal betaImag=beta.imag, betaReal=beta.real;
-
878 
-
879  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
880  if (thisTask>=numTasks) return;
-
881 
-
882  thisBlock = thisTask / sizeHalfBlock;
-
883  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
884  indexLo = indexUp + sizeHalfBlock;
-
885 
-
886  controlBit = extractBit(controlQubit, indexUp);
-
887  if (controlBit){
-
888  // store current state vector values in temp variables
-
889  stateRealUp = stateVecReal[indexUp];
-
890  stateImagUp = stateVecImag[indexUp];
-
891 
-
892  stateRealLo = stateVecReal[indexLo];
-
893  stateImagLo = stateVecImag[indexLo];
-
894 
-
895  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
896  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
897  - betaReal*stateRealLo - betaImag*stateImagLo;
-
898  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
899  - betaReal*stateImagLo + betaImag*stateRealLo;
-
900 
-
901  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
902  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
903  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
904  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
905  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
906  }
-
907 }
+
872  // rotate //
+
873  // ---------------------------------------------------------------- //
+
874 
+
876  qreal *stateVecReal = qureg.deviceStateVec.real;
+
877  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
878  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
879  qreal betaImag=beta.imag, betaReal=beta.real;
+
880 
+
881  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
882  if (thisTask>=numTasks) return;
+
883 
+
884  thisBlock = thisTask / sizeHalfBlock;
+
885  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
886  indexLo = indexUp + sizeHalfBlock;
+
887 
+
888  controlBit = extractBit(controlQubit, indexUp);
+
889  if (controlBit){
+
890  // store current state vector values in temp variables
+
891  stateRealUp = stateVecReal[indexUp];
+
892  stateImagUp = stateVecImag[indexUp];
+
893 
+
894  stateRealLo = stateVecReal[indexLo];
+
895  stateImagLo = stateVecImag[indexLo];
+
896 
+
897  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
898  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
899  - betaReal*stateRealLo - betaImag*stateImagLo;
+
900  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
901  - betaReal*stateImagLo + betaImag*stateRealLo;
+
902 
+
903  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
904  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
905  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
906  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
907  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
908  }
+
909 }

References Qureg::deviceStateVec, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

@@ -6361,17 +6361,17 @@

-

Definition at line 1871 of file QuEST_gpu.cu.

-
1872 {
-
1873  int threadsPerCUDABlock, CUDABlocks;
-
1874  threadsPerCUDABlock = 128;
-
1875  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1876  statevec_controlledNotKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit);
-
1877 }
+

Definition at line 1873 of file QuEST_gpu.cu.

+
1874 {
+
1875  int threadsPerCUDABlock, CUDABlocks;
+
1876  threadsPerCUDABlock = 128;
+
1877  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1878  statevec_controlledNotKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit);
+
1879 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledNot().

+

Referenced by controlledNot().

@@ -6407,44 +6407,44 @@

-

Definition at line 1832 of file QuEST_gpu.cu.

-
1833 {
-
1834  long long int index;
-
1835  long long int sizeBlock, // size of blocks
-
1836  sizeHalfBlock; // size of blocks halved
-
1837  long long int stateVecSize;
-
1838  int controlBit;
-
1839 
-
1840  // ----- temp variables
-
1841  qreal stateRealUp, // storage for previous state values
-
1842  stateImagUp; // (used in updates)
-
1843  long long int thisBlock, // current block
-
1844  indexUp,indexLo; // current index and corresponding index in lower half block
-
1845  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1846  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1847 
-
1848  stateVecSize = qureg.numAmpsPerChunk;
-
1849  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1850  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1851 
-
1852  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1853  if (index>=(stateVecSize>>1)) return;
-
1854  thisBlock = index / sizeHalfBlock;
-
1855  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1856  indexLo = indexUp + sizeHalfBlock;
-
1857 
-
1858  controlBit = extractBit(controlQubit, indexUp);
-
1859  if (controlBit){
-
1860  stateRealUp = stateVecReal[indexUp];
-
1861  stateImagUp = stateVecImag[indexUp];
-
1862 
-
1863  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1864  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1865 
-
1866  stateVecReal[indexLo] = stateRealUp;
-
1867  stateVecImag[indexLo] = stateImagUp;
-
1868  }
-
1869 }
+

Definition at line 1834 of file QuEST_gpu.cu.

+
1835 {
+
1836  long long int index;
+
1837  long long int sizeBlock, // size of blocks
+
1838  sizeHalfBlock; // size of blocks halved
+
1839  long long int stateVecSize;
+
1840  int controlBit;
+
1841 
+
1842  // ----- temp variables
+
1843  qreal stateRealUp, // storage for previous state values
+
1844  stateImagUp; // (used in updates)
+
1845  long long int thisBlock, // current block
+
1846  indexUp,indexLo; // current index and corresponding index in lower half block
+
1847  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1848  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1849 
+
1850  stateVecSize = qureg.numAmpsPerChunk;
+
1851  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1852  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1853 
+
1854  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1855  if (index>=(stateVecSize>>1)) return;
+
1856  thisBlock = index / sizeHalfBlock;
+
1857  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
+
1858  indexLo = indexUp + sizeHalfBlock;
+
1859 
+
1860  controlBit = extractBit(controlQubit, indexUp);
+
1861  if (controlBit){
+
1862  stateRealUp = stateVecReal[indexUp];
+
1863  stateImagUp = stateVecImag[indexUp];
+
1864 
+
1865  stateVecReal[indexUp] = stateVecReal[indexLo];
+
1866  stateVecImag[indexUp] = stateVecImag[indexLo];
+
1867 
+
1868  stateVecReal[indexLo] = stateRealUp;
+
1869  stateVecImag[indexLo] = stateImagUp;
+
1870  }
+
1871 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

@@ -6482,18 +6482,18 @@

-

Definition at line 1443 of file QuEST_gpu.cu.

-
1444 {
-
1445  int conjFactor = 1;
-
1446  int threadsPerCUDABlock, CUDABlocks;
-
1447  threadsPerCUDABlock = 128;
-
1448  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1449  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1450 }
+

Definition at line 1445 of file QuEST_gpu.cu.

+
1446 {
+
1447  int conjFactor = 1;
+
1448  int threadsPerCUDABlock, CUDABlocks;
+
1449  threadsPerCUDABlock = 128;
+
1450  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1451  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
+
1452 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledPauliY().

+

Referenced by controlledPauliY().

@@ -6529,18 +6529,18 @@

-

Definition at line 1452 of file QuEST_gpu.cu.

-
1453 {
-
1454  int conjFactor = -1;
-
1455  int threadsPerCUDABlock, CUDABlocks;
-
1456  threadsPerCUDABlock = 128;
-
1457  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1458  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1459 }
+

Definition at line 1454 of file QuEST_gpu.cu.

+
1455 {
+
1456  int conjFactor = -1;
+
1457  int threadsPerCUDABlock, CUDABlocks;
+
1458  threadsPerCUDABlock = 128;
+
1459  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1460  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
+
1461 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledPauliY().

+

Referenced by controlledPauliY().

@@ -6582,41 +6582,41 @@

-

Definition at line 1407 of file QuEST_gpu.cu.

-
1408 {
-
1409  long long int index;
-
1410  long long int sizeBlock, sizeHalfBlock;
-
1411  long long int stateVecSize;
-
1412  int controlBit;
-
1413 
-
1414  qreal stateRealUp, stateImagUp;
-
1415  long long int thisBlock, indexUp, indexLo;
-
1416  sizeHalfBlock = 1LL << targetQubit;
-
1417  sizeBlock = 2LL * sizeHalfBlock;
-
1418 
-
1419  stateVecSize = qureg.numAmpsPerChunk;
-
1420  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1421  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1422 
-
1423  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1424  if (index>=(stateVecSize>>1)) return;
-
1425  thisBlock = index / sizeHalfBlock;
-
1426  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1427  indexLo = indexUp + sizeHalfBlock;
-
1428 
-
1429  controlBit = extractBit(controlQubit, indexUp);
-
1430  if (controlBit){
-
1431 
-
1432  stateRealUp = stateVecReal[indexUp];
-
1433  stateImagUp = stateVecImag[indexUp];
-
1434 
-
1435  // update under +-{{0, -i}, {i, 0}}
-
1436  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1437  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1438  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1439  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1440  }
-
1441 }
+

Definition at line 1409 of file QuEST_gpu.cu.

+
1410 {
+
1411  long long int index;
+
1412  long long int sizeBlock, sizeHalfBlock;
+
1413  long long int stateVecSize;
+
1414  int controlBit;
+
1415 
+
1416  qreal stateRealUp, stateImagUp;
+
1417  long long int thisBlock, indexUp, indexLo;
+
1418  sizeHalfBlock = 1LL << targetQubit;
+
1419  sizeBlock = 2LL * sizeHalfBlock;
+
1420 
+
1421  stateVecSize = qureg.numAmpsPerChunk;
+
1422  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1423  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1424 
+
1425  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1426  if (index>=(stateVecSize>>1)) return;
+
1427  thisBlock = index / sizeHalfBlock;
+
1428  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
+
1429  indexLo = indexUp + sizeHalfBlock;
+
1430 
+
1431  controlBit = extractBit(controlQubit, indexUp);
+
1432  if (controlBit){
+
1433 
+
1434  stateRealUp = stateVecReal[indexUp];
+
1435  stateImagUp = stateVecImag[indexUp];
+
1436 
+
1437  // update under +-{{0, -i}, {i, 0}}
+
1438  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
1439  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
1440  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
1441  stateVecImag[indexLo] = conjFac * stateRealUp;
+
1442  }
+
1443 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

@@ -6654,17 +6654,17 @@

-

Definition at line 1706 of file QuEST_gpu.cu.

-
1707 {
-
1708  int threadsPerCUDABlock, CUDABlocks;
-
1709  threadsPerCUDABlock = 128;
-
1710  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1711  statevec_controlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2);
-
1712 }
+

Definition at line 1708 of file QuEST_gpu.cu.

+
1709 {
+
1710  int threadsPerCUDABlock, CUDABlocks;
+
1711  threadsPerCUDABlock = 128;
+
1712  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1713  statevec_controlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2);
+
1714 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledPhaseFlip().

+

Referenced by controlledPhaseFlip().

@@ -6700,26 +6700,26 @@

-

Definition at line 1685 of file QuEST_gpu.cu.

-
1686 {
-
1687  long long int index;
-
1688  long long int stateVecSize;
-
1689  int bit1, bit2;
-
1690 
-
1691  stateVecSize = qureg.numAmpsPerChunk;
-
1692  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1693  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1694 
-
1695  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1696  if (index>=stateVecSize) return;
-
1697 
-
1698  bit1 = extractBit (idQubit1, index);
-
1699  bit2 = extractBit (idQubit2, index);
-
1700  if (bit1 && bit2) {
-
1701  stateVecReal [index] = - stateVecReal [index];
-
1702  stateVecImag [index] = - stateVecImag [index];
-
1703  }
-
1704 }
+

Definition at line 1687 of file QuEST_gpu.cu.

+
1688 {
+
1689  long long int index;
+
1690  long long int stateVecSize;
+
1691  int bit1, bit2;
+
1692 
+
1693  stateVecSize = qureg.numAmpsPerChunk;
+
1694  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1695  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1696 
+
1697  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1698  if (index>=stateVecSize) return;
+
1699 
+
1700  bit1 = extractBit (idQubit1, index);
+
1701  bit2 = extractBit (idQubit2, index);
+
1702  if (bit1 && bit2) {
+
1703  stateVecReal [index] = - stateVecReal [index];
+
1704  stateVecImag [index] = - stateVecImag [index];
+
1705  }
+
1706 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

@@ -6763,20 +6763,20 @@

-

Definition at line 1525 of file QuEST_gpu.cu.

-
1526 {
-
1527  qreal cosAngle = cos(angle);
-
1528  qreal sinAngle = sin(angle);
-
1529 
-
1530  int threadsPerCUDABlock, CUDABlocks;
-
1531  threadsPerCUDABlock = 128;
-
1532  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1533  statevec_controlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2, cosAngle, sinAngle);
-
1534 }
+

Definition at line 1527 of file QuEST_gpu.cu.

+
1528 {
+
1529  qreal cosAngle = cos(angle);
+
1530  qreal sinAngle = sin(angle);
+
1531 
+
1532  int threadsPerCUDABlock, CUDABlocks;
+
1533  threadsPerCUDABlock = 128;
+
1534  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1535  statevec_controlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2, cosAngle, sinAngle);
+
1536 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledPhaseShift().

+

Referenced by controlledPhaseShift().

@@ -6824,30 +6824,30 @@

-

Definition at line 1500 of file QuEST_gpu.cu.

-
1501 {
-
1502  long long int index;
-
1503  long long int stateVecSize;
-
1504  int bit1, bit2;
-
1505  qreal stateRealLo, stateImagLo;
-
1506 
-
1507  stateVecSize = qureg.numAmpsPerChunk;
-
1508  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1509  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1510 
-
1511  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1512  if (index>=stateVecSize) return;
-
1513 
-
1514  bit1 = extractBit (idQubit1, index);
-
1515  bit2 = extractBit (idQubit2, index);
-
1516  if (bit1 && bit2) {
-
1517  stateRealLo = stateVecReal[index];
-
1518  stateImagLo = stateVecImag[index];
-
1519 
-
1520  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1521  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1522  }
-
1523 }
+

Definition at line 1502 of file QuEST_gpu.cu.

+
1503 {
+
1504  long long int index;
+
1505  long long int stateVecSize;
+
1506  int bit1, bit2;
+
1507  qreal stateRealLo, stateImagLo;
+
1508 
+
1509  stateVecSize = qureg.numAmpsPerChunk;
+
1510  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1511  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1512 
+
1513  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1514  if (index>=stateVecSize) return;
+
1515 
+
1516  bit1 = extractBit (idQubit1, index);
+
1517  bit2 = extractBit (idQubit2, index);
+
1518  if (bit1 && bit2) {
+
1519  stateRealLo = stateVecReal[index];
+
1520  stateImagLo = stateVecImag[index];
+
1521 
+
1522  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
1523  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
1524  }
+
1525 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

@@ -6891,17 +6891,17 @@

-

Definition at line 1235 of file QuEST_gpu.cu.

-
1236 {
-
1237  int threadsPerCUDABlock, CUDABlocks;
-
1238  threadsPerCUDABlock = 128;
-
1239  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1240  statevec_controlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, argifyMatrix2(u));
-
1241 }
+

Definition at line 1237 of file QuEST_gpu.cu.

+
1238 {
+
1239  int threadsPerCUDABlock, CUDABlocks;
+
1240  threadsPerCUDABlock = 128;
+
1241  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1242  statevec_controlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, argifyMatrix2(u));
+
1243 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by controlledUnitary().

+

Referenced by controlledUnitary().

@@ -6944,63 +6944,63 @@

fix – no necessary for GPU version

-

Definition at line 1177 of file QuEST_gpu.cu.

-
1177  {
-
1178  // ----- sizes
-
1179  long long int sizeBlock, // size of blocks
-
1180  sizeHalfBlock; // size of blocks halved
-
1181  // ----- indices
-
1182  long long int thisBlock, // current block
-
1183  indexUp,indexLo; // current index and corresponding index in lower half block
-
1184 
-
1185  // ----- temp variables
-
1186  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1187  stateImagUp,stateImagLo; // (used in updates)
-
1188  // ----- temp variables
-
1189  long long int thisTask; // task based approach for expose loop with small granularity
-
1190  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1191 
-
1192  int controlBit;
+

Definition at line 1179 of file QuEST_gpu.cu.

+
1179  {
+
1180  // ----- sizes
+
1181  long long int sizeBlock, // size of blocks
+
1182  sizeHalfBlock; // size of blocks halved
+
1183  // ----- indices
+
1184  long long int thisBlock, // current block
+
1185  indexUp,indexLo; // current index and corresponding index in lower half block
+
1186 
+
1187  // ----- temp variables
+
1188  qreal stateRealUp,stateRealLo, // storage for previous state values
+
1189  stateImagUp,stateImagLo; // (used in updates)
+
1190  // ----- temp variables
+
1191  long long int thisTask; // task based approach for expose loop with small granularity
+
1192  long long int numTasks=qureg.numAmpsPerChunk>>1;
1193 
-
1194  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1195  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1196 
-
1197  // ---------------------------------------------------------------- //
-
1198  // rotate //
+
1194  int controlBit;
+
1195 
+
1196  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1197  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1198 
1199  // ---------------------------------------------------------------- //
-
1200 
-
1202  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1203  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1204 
-
1205  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1206  if (thisTask>=numTasks) return;
-
1207 
-
1208  thisBlock = thisTask / sizeHalfBlock;
-
1209  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1210  indexLo = indexUp + sizeHalfBlock;
-
1211 
-
1212  // store current state vector values in temp variables
-
1213  stateRealUp = stateVecReal[indexUp];
-
1214  stateImagUp = stateVecImag[indexUp];
-
1215 
-
1216  stateRealLo = stateVecReal[indexLo];
-
1217  stateImagLo = stateVecImag[indexLo];
-
1218 
-
1219  controlBit = extractBit(controlQubit, indexUp);
-
1220  if (controlBit){
-
1221  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1222  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1223  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1224  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1225  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1226 
-
1227  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1228  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1229  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1230  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1231  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1232  }
-
1233 }
+
1200  // rotate //
+
1201  // ---------------------------------------------------------------- //
+
1202 
+
1204  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1205  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1206 
+
1207  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1208  if (thisTask>=numTasks) return;
+
1209 
+
1210  thisBlock = thisTask / sizeHalfBlock;
+
1211  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1212  indexLo = indexUp + sizeHalfBlock;
+
1213 
+
1214  // store current state vector values in temp variables
+
1215  stateRealUp = stateVecReal[indexUp];
+
1216  stateImagUp = stateVecImag[indexUp];
+
1217 
+
1218  stateRealLo = stateVecReal[indexLo];
+
1219  stateImagLo = stateVecImag[indexLo];
+
1220 
+
1221  controlBit = extractBit(controlQubit, indexUp);
+
1222  if (controlBit){
+
1223  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
1224  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
+
1225  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
+
1226  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
+
1227  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
+
1228 
+
1229  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
1230  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
+
1231  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
+
1232  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
+
1233  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
+
1234  }
+
1235 }

References Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, and qreal.

@@ -7084,7 +7084,7 @@

318 

319 }
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, qreal, QuESTEnv::rank, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and Qureg::stateVec.

+

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, qreal, QuESTEnv::rank, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and Qureg::stateVec.

Referenced by createCloneQureg(), createDensityQureg(), and createQureg().

@@ -7133,7 +7133,7 @@

335  cudaFree(qureg.secondLevelReduction);
336 }
-

References Qureg::deviceStateVec, Qureg::firstLevelReduction, QuESTEnv::numRanks, Qureg::pairStateVec, Qureg::secondLevelReduction, and Qureg::stateVec.

+

References Qureg::deviceStateVec, Qureg::firstLevelReduction, QuESTEnv::numRanks, Qureg::pairStateVec, Qureg::secondLevelReduction, and Qureg::stateVec.

Referenced by destroyQureg().

@@ -7165,47 +7165,47 @@

-

Definition at line 2110 of file QuEST_gpu.cu.

-
2111 {
-
2112  long long int numValuesToReduce = qureg.numAmpsPerChunk>>1;
-
2113  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2114  qreal stateProb=0;
-
2115  int firstTime=1;
-
2116  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2117 
-
2118  while(numValuesToReduce>1){
-
2119  if (numValuesToReduce<maxReducedPerLevel){
-
2120  // Need less than one CUDA block to reduce values
-
2121  valuesPerCUDABlock = numValuesToReduce;
-
2122  numCUDABlocks = 1;
-
2123  } else {
-
2124  // Use full CUDA blocks, with block size constrained by shared mem usage
-
2125  valuesPerCUDABlock = maxReducedPerLevel;
-
2126  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2127  }
-
2128  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2129 
-
2130  if (firstTime){
-
2131  statevec_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2132  qureg, measureQubit, qureg.firstLevelReduction);
-
2133  firstTime=0;
-
2134  } else {
-
2135  cudaDeviceSynchronize();
-
2136  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2137  qureg.firstLevelReduction,
-
2138  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2139  cudaDeviceSynchronize();
- -
2141  }
-
2142  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2143  }
-
2144  cudaMemcpy(&stateProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2145  return stateProb;
-
2146 }
+

Definition at line 2112 of file QuEST_gpu.cu.

+
2113 {
+
2114  long long int numValuesToReduce = qureg.numAmpsPerChunk>>1;
+
2115  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2116  qreal stateProb=0;
+
2117  int firstTime=1;
+
2118  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2119 
+
2120  while(numValuesToReduce>1){
+
2121  if (numValuesToReduce<maxReducedPerLevel){
+
2122  // Need less than one CUDA block to reduce values
+
2123  valuesPerCUDABlock = numValuesToReduce;
+
2124  numCUDABlocks = 1;
+
2125  } else {
+
2126  // Use full CUDA blocks, with block size constrained by shared mem usage
+
2127  valuesPerCUDABlock = maxReducedPerLevel;
+
2128  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2129  }
+
2130  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2131 
+
2132  if (firstTime){
+
2133  statevec_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2134  qureg, measureQubit, qureg.firstLevelReduction);
+
2135  firstTime=0;
+
2136  } else {
+
2137  cudaDeviceSynchronize();
+
2138  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2139  qureg.firstLevelReduction,
+
2140  qureg.secondLevelReduction, valuesPerCUDABlock);
+
2141  cudaDeviceSynchronize();
+ +
2143  }
+
2144  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2145  }
+
2146  cudaMemcpy(&stateProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2147  return stateProb;
+
2148 }
-

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+

References copySharedReduceBlock(), Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

-

Referenced by statevec_calcProbOfOutcome().

+

Referenced by statevec_calcProbOfOutcome().

@@ -7241,56 +7241,56 @@

-

Definition at line 1996 of file QuEST_gpu.cu.

-
1998  {
-
1999  // ----- sizes
-
2000  long long int sizeBlock, // size of blocks
-
2001  sizeHalfBlock; // size of blocks halved
-
2002  // ----- indices
-
2003  long long int thisBlock, // current block
-
2004  index; // current index for first half block
-
2005  // ----- temp variables
-
2006  long long int thisTask; // task based approach for expose loop with small granularity
-
2007  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2008  // (good for shared memory parallelism)
-
2009 
-
2010  extern __shared__ qreal tempReductionArray[];
+

Definition at line 1998 of file QuEST_gpu.cu.

+
2000  {
+
2001  // ----- sizes
+
2002  long long int sizeBlock, // size of blocks
+
2003  sizeHalfBlock; // size of blocks halved
+
2004  // ----- indices
+
2005  long long int thisBlock, // current block
+
2006  index; // current index for first half block
+
2007  // ----- temp variables
+
2008  long long int thisTask; // task based approach for expose loop with small granularity
+
2009  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2010  // (good for shared memory parallelism)
2011 
-
2012  // ---------------------------------------------------------------- //
-
2013  // dimensions //
+
2012  extern __shared__ qreal tempReductionArray[];
+
2013 
2014  // ---------------------------------------------------------------- //
-
2015  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
2016  // and then the number to skip
-
2017  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
2018 
-
2019  // ---------------------------------------------------------------- //
-
2020  // find probability //
+
2015  // dimensions //
+
2016  // ---------------------------------------------------------------- //
+
2017  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
2018  // and then the number to skip
+
2019  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
2020 
2021  // ---------------------------------------------------------------- //
-
2022 
-
2023  //
-
2024  // --- task-based shared-memory parallel implementation
+
2022  // find probability //
+
2023  // ---------------------------------------------------------------- //
+
2024 
2025  //
-
2026 
-
2027  qreal *stateVecReal = qureg.deviceStateVec.real;
-
2028  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
2029 
-
2030  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2031  if (thisTask>=numTasks) return;
-
2032 
-
2033  thisBlock = thisTask / sizeHalfBlock;
-
2034  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2035  qreal realVal, imagVal;
-
2036  realVal = stateVecReal[index];
-
2037  imagVal = stateVecImag[index];
-
2038  tempReductionArray[threadIdx.x] = realVal*realVal + imagVal*imagVal;
-
2039  __syncthreads();
-
2040 
-
2041  if (threadIdx.x<blockDim.x/2){
-
2042  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2043  }
-
2044 }
-
-

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and reduceBlock().

+
2026  // --- task-based shared-memory parallel implementation
+
2027  //
+
2028 
+
2029  qreal *stateVecReal = qureg.deviceStateVec.real;
+
2030  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
2031 
+
2032  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
2033  if (thisTask>=numTasks) return;
+
2034 
+
2035  thisBlock = thisTask / sizeHalfBlock;
+
2036  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2037  qreal realVal, imagVal;
+
2038  realVal = stateVecReal[index];
+
2039  imagVal = stateVecImag[index];
+
2040  tempReductionArray[threadIdx.x] = realVal*realVal + imagVal*imagVal;
+
2041  __syncthreads();
+
2042 
+
2043  if (threadIdx.x<blockDim.x/2){
+
2044  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2045  }
+
2046 }
+
+

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and reduceBlock().

@@ -7320,17 +7320,17 @@

-

Definition at line 574 of file QuEST_gpu.cu.

-
574  {
-
575  qreal el=0;
-
576  cudaMemcpy(&el, &(qureg.deviceStateVec.imag[index]),
-
577  sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
-
578  return el;
-
579 }
+

Definition at line 576 of file QuEST_gpu.cu.

+
576  {
+
577  qreal el=0;
+
578  cudaMemcpy(&el, &(qureg.deviceStateVec.imag[index]),
+
579  sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
+
580  return el;
+
581 }

References Qureg::deviceStateVec, and qreal.

-

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

+

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

@@ -7360,17 +7360,17 @@

-

Definition at line 567 of file QuEST_gpu.cu.

-
567  {
-
568  qreal el=0;
-
569  cudaMemcpy(&el, &(qureg.deviceStateVec.real[index]),
-
570  sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
-
571  return el;
-
572 }
+

Definition at line 569 of file QuEST_gpu.cu.

+
569  {
+
570  qreal el=0;
+
571  cudaMemcpy(&el, &(qureg.deviceStateVec.real[index]),
+
572  sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
+
573  return el;
+
574 }

References Qureg::deviceStateVec, and qreal.

-

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

+

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

@@ -7400,17 +7400,17 @@

-

Definition at line 1824 of file QuEST_gpu.cu.

-
1825 {
-
1826  int threadsPerCUDABlock, CUDABlocks;
-
1827  threadsPerCUDABlock = 128;
-
1828  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1829  statevec_hadamardKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1830 }
+

Definition at line 1826 of file QuEST_gpu.cu.

+
1827 {
+
1828  int threadsPerCUDABlock, CUDABlocks;
+
1829  threadsPerCUDABlock = 128;
+
1830  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1831  statevec_hadamardKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
+
1832 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by agnostic_applyQFT(), and hadamard().

+

Referenced by agnostic_applyQFT(), and hadamard().

@@ -7441,54 +7441,54 @@

fix – no necessary for GPU version

-

Definition at line 1775 of file QuEST_gpu.cu.

-
1775  {
-
1776  // ----- sizes
-
1777  long long int sizeBlock, // size of blocks
-
1778  sizeHalfBlock; // size of blocks halved
-
1779  // ----- indices
-
1780  long long int thisBlock, // current block
-
1781  indexUp,indexLo; // current index and corresponding index in lower half block
-
1782 
-
1783  // ----- temp variables
-
1784  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1785  stateImagUp,stateImagLo; // (used in updates)
-
1786  // ----- temp variables
-
1787  long long int thisTask; // task based approach for expose loop with small granularity
-
1788  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1789 
-
1790  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1791  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1792 
-
1793  // ---------------------------------------------------------------- //
-
1794  // rotate //
+

Definition at line 1777 of file QuEST_gpu.cu.

+
1777  {
+
1778  // ----- sizes
+
1779  long long int sizeBlock, // size of blocks
+
1780  sizeHalfBlock; // size of blocks halved
+
1781  // ----- indices
+
1782  long long int thisBlock, // current block
+
1783  indexUp,indexLo; // current index and corresponding index in lower half block
+
1784 
+
1785  // ----- temp variables
+
1786  qreal stateRealUp,stateRealLo, // storage for previous state values
+
1787  stateImagUp,stateImagLo; // (used in updates)
+
1788  // ----- temp variables
+
1789  long long int thisTask; // task based approach for expose loop with small granularity
+
1790  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1791 
+
1792  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1793  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1794 
1795  // ---------------------------------------------------------------- //
-
1796 
-
1798  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1799  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1800 
-
1801  qreal recRoot2 = 1.0/sqrt(2.0);
+
1796  // rotate //
+
1797  // ---------------------------------------------------------------- //
+
1798 
+
1800  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1801  qreal *stateVecImag = qureg.deviceStateVec.imag;
1802 
-
1803  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1804  if (thisTask>=numTasks) return;
-
1805 
-
1806  thisBlock = thisTask / sizeHalfBlock;
-
1807  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1808  indexLo = indexUp + sizeHalfBlock;
-
1809 
-
1810  // store current state vector values in temp variables
-
1811  stateRealUp = stateVecReal[indexUp];
-
1812  stateImagUp = stateVecImag[indexUp];
-
1813 
-
1814  stateRealLo = stateVecReal[indexLo];
-
1815  stateImagLo = stateVecImag[indexLo];
-
1816 
-
1817  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
1818  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
1819 
-
1820  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
1821  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
1822 }
+
1803  qreal recRoot2 = 1.0/sqrt(2.0);
+
1804 
+
1805  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1806  if (thisTask>=numTasks) return;
+
1807 
+
1808  thisBlock = thisTask / sizeHalfBlock;
+
1809  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1810  indexLo = indexUp + sizeHalfBlock;
+
1811 
+
1812  // store current state vector values in temp variables
+
1813  stateRealUp = stateVecReal[indexUp];
+
1814  stateImagUp = stateVecImag[indexUp];
+
1815 
+
1816  stateRealLo = stateVecReal[indexLo];
+
1817  stateImagLo = stateVecImag[indexLo];
+
1818 
+
1819  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
+
1820  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
+
1821 
+
1822  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
+
1823  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
+
1824 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -7510,20 +7510,20 @@

-

Definition at line 591 of file QuEST_gpu.cu.

-
592 {
-
593  int threadsPerCUDABlock, CUDABlocks;
-
594  threadsPerCUDABlock = 128;
-
595  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
596  statevec_initBlankStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
597  qureg.numAmpsPerChunk,
-
598  qureg.deviceStateVec.real,
-
599  qureg.deviceStateVec.imag);
-
600 }
+

Definition at line 593 of file QuEST_gpu.cu.

+
594 {
+
595  int threadsPerCUDABlock, CUDABlocks;
+
596  threadsPerCUDABlock = 128;
+
597  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
598  statevec_initBlankStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
599  qureg.numAmpsPerChunk,
+
600  qureg.deviceStateVec.real,
+
601  qureg.deviceStateVec.imag);
+
602 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

-

Referenced by initBlankState(), and statevec_applyPauliSum().

+

Referenced by initBlankState(), and statevec_applyPauliSum().

@@ -7559,16 +7559,16 @@

-

Definition at line 581 of file QuEST_gpu.cu.

-
581  {
-
582  long long int index;
-
583 
-
584  // initialise the statevector to be all-zeros
-
585  index = blockIdx.x*blockDim.x + threadIdx.x;
-
586  if (index>=stateVecSize) return;
-
587  stateVecReal[index] = 0.0;
-
588  stateVecImag[index] = 0.0;
-
589 }
+

Definition at line 583 of file QuEST_gpu.cu.

+
583  {
+
584  long long int index;
+
585 
+
586  // initialise the statevector to be all-zeros
+
587  index = blockIdx.x*blockDim.x + threadIdx.x;
+
588  if (index>=stateVecSize) return;
+
589  stateVecReal[index] = 0.0;
+
590  stateVecImag[index] = 0.0;
+
591 }
@@ -7598,16 +7598,16 @@

-

Definition at line 666 of file QuEST_gpu.cu.

-
667 {
-
668  int threadsPerCUDABlock, CUDABlocks;
-
669  threadsPerCUDABlock = 128;
-
670  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
671  statevec_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
672  qureg.numAmpsPerChunk,
-
673  qureg.deviceStateVec.real,
-
674  qureg.deviceStateVec.imag, stateInd);
-
675 }
+

Definition at line 668 of file QuEST_gpu.cu.

+
669 {
+
670  int threadsPerCUDABlock, CUDABlocks;
+
671  threadsPerCUDABlock = 128;
+
672  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
673  statevec_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
674  qureg.numAmpsPerChunk,
+
675  qureg.deviceStateVec.real,
+
676  qureg.deviceStateVec.imag, stateInd);
+
677 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -7653,22 +7653,22 @@

-

Definition at line 651 of file QuEST_gpu.cu.

-
651  {
-
652  long long int index;
-
653 
-
654  // initialise the state to |stateInd>
-
655  index = blockIdx.x*blockDim.x + threadIdx.x;
-
656  if (index>=stateVecSize) return;
-
657  stateVecReal[index] = 0.0;
-
658  stateVecImag[index] = 0.0;
-
659 
-
660  if (index==stateInd){
-
661  // classical state has probability 1
-
662  stateVecReal[stateInd] = 1.0;
-
663  stateVecImag[stateInd] = 0.0;
-
664  }
-
665 }
+

Definition at line 653 of file QuEST_gpu.cu.

+
653  {
+
654  long long int index;
+
655 
+
656  // initialise the state to |stateInd>
+
657  index = blockIdx.x*blockDim.x + threadIdx.x;
+
658  if (index>=stateVecSize) return;
+
659  stateVecReal[index] = 0.0;
+
660  stateVecImag[index] = 0.0;
+
661 
+
662  if (index==stateInd){
+
663  // classical state has probability 1
+
664  stateVecReal[stateInd] = 1.0;
+
665  stateVecImag[stateInd] = 0.0;
+
666  }
+
667 }

@@ -7696,20 +7696,20 @@

Definition at line 687 of file QuEST_gpu.cu.

-
688 {
-
689  int threadsPerCUDABlock, CUDABlocks;
-
690  threadsPerCUDABlock = 128;
-
691  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
692  statevec_initDebugStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
693  qureg.numAmpsPerChunk,
-
694  qureg.deviceStateVec.real,
-
695  qureg.deviceStateVec.imag);
-
696 }
+

Definition at line 689 of file QuEST_gpu.cu.

+
690 {
+
691  int threadsPerCUDABlock, CUDABlocks;
+
692  threadsPerCUDABlock = 128;
+
693  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
694  statevec_initDebugStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
695  qureg.numAmpsPerChunk,
+
696  qureg.deviceStateVec.real,
+
697  qureg.deviceStateVec.imag);
+
698 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

-

Referenced by initDebugState().

+

Referenced by initDebugState().

@@ -7745,16 +7745,16 @@

-

Definition at line 677 of file QuEST_gpu.cu.

-
677  {
-
678  long long int index;
-
679 
-
680  index = blockIdx.x*blockDim.x + threadIdx.x;
-
681  if (index>=stateVecSize) return;
-
682 
-
683  stateVecReal[index] = (index*2.0)/10.0;
-
684  stateVecImag[index] = (index*2.0+1.0)/10.0;
-
685 }
+

Definition at line 679 of file QuEST_gpu.cu.

+
679  {
+
680  long long int index;
+
681 
+
682  index = blockIdx.x*blockDim.x + threadIdx.x;
+
683  if (index>=stateVecSize) return;
+
684 
+
685  stateVecReal[index] = (index*2.0)/10.0;
+
686  stateVecImag[index] = (index*2.0+1.0)/10.0;
+
687 }
@@ -7774,16 +7774,16 @@

-

Definition at line 640 of file QuEST_gpu.cu.

-
641 {
-
642  int threadsPerCUDABlock, CUDABlocks;
-
643  threadsPerCUDABlock = 128;
-
644  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
645  statevec_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
646  qureg.numAmpsPerChunk,
-
647  qureg.deviceStateVec.real,
-
648  qureg.deviceStateVec.imag);
-
649 }
+

Definition at line 642 of file QuEST_gpu.cu.

+
643 {
+
644  int threadsPerCUDABlock, CUDABlocks;
+
645  threadsPerCUDABlock = 128;
+
646  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
647  statevec_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
648  qureg.numAmpsPerChunk,
+
649  qureg.deviceStateVec.real,
+
650  qureg.deviceStateVec.imag);
+
651 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -7823,17 +7823,17 @@

-

Definition at line 629 of file QuEST_gpu.cu.

-
629  {
-
630  long long int index;
-
631 
-
632  index = blockIdx.x*blockDim.x + threadIdx.x;
-
633  if (index>=stateVecSize) return;
-
634 
-
635  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
636  stateVecReal[index] = normFactor;
-
637  stateVecImag[index] = 0.0;
-
638 }
+

Definition at line 631 of file QuEST_gpu.cu.

+
631  {
+
632  long long int index;
+
633 
+
634  index = blockIdx.x*blockDim.x + threadIdx.x;
+
635  if (index>=stateVecSize) return;
+
636 
+
637  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
+
638  stateVecReal[index] = normFactor;
+
639  stateVecImag[index] = 0.0;
+
640 }

References qreal.

@@ -7871,54 +7871,54 @@

-

Definition at line 725 of file QuEST_gpu.cu.

-
725  {
-
726  long long int chunkSize, stateVecSize;
-
727  long long int indexInChunk, totalIndex;
-
728 
-
729  chunkSize = qureg->numAmpsPerChunk;
-
730  stateVecSize = chunkSize*qureg->numChunks;
-
731 
-
732  qreal *stateVecReal = qureg->stateVec.real;
-
733  qreal *stateVecImag = qureg->stateVec.imag;
-
734 
-
735  FILE *fp;
-
736  char line[200];
-
737 
-
738  fp = fopen(filename, "r");
-
739  if (fp == NULL)
-
740  return 0;
-
741 
-
742  indexInChunk = 0; totalIndex = 0;
-
743  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
744  if (line[0]!='#'){
-
745  int chunkId = totalIndex/chunkSize;
-
746  if (chunkId==qureg->chunkId){
-
747  # if QuEST_PREC==1
-
748  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
749  &(stateVecImag[indexInChunk]));
-
750  # elif QuEST_PREC==2
-
751  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
752  &(stateVecImag[indexInChunk]));
-
753  # elif QuEST_PREC==4
-
754  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
755  &(stateVecImag[indexInChunk]));
-
756  # endif
-
757  indexInChunk += 1;
-
758  }
-
759  totalIndex += 1;
-
760  }
-
761  }
-
762  fclose(fp);
-
763  copyStateToGPU(*qureg);
-
764 
-
765  // indicate success
-
766  return 1;
-
767 }
-
-

References Qureg::chunkId, copyStateToGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

- -

Referenced by initStateFromSingleFile().

+

Definition at line 727 of file QuEST_gpu.cu.

+
727  {
+
728  long long int chunkSize, stateVecSize;
+
729  long long int indexInChunk, totalIndex;
+
730 
+
731  chunkSize = qureg->numAmpsPerChunk;
+
732  stateVecSize = chunkSize*qureg->numChunks;
+
733 
+
734  qreal *stateVecReal = qureg->stateVec.real;
+
735  qreal *stateVecImag = qureg->stateVec.imag;
+
736 
+
737  FILE *fp;
+
738  char line[200];
+
739 
+
740  fp = fopen(filename, "r");
+
741  if (fp == NULL)
+
742  return 0;
+
743 
+
744  indexInChunk = 0; totalIndex = 0;
+
745  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
+
746  if (line[0]!='#'){
+
747  int chunkId = totalIndex/chunkSize;
+
748  if (chunkId==qureg->chunkId){
+
749  # if QuEST_PREC==1
+
750  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
+
751  &(stateVecImag[indexInChunk]));
+
752  # elif QuEST_PREC==2
+
753  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
754  &(stateVecImag[indexInChunk]));
+
755  # elif QuEST_PREC==4
+
756  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
757  &(stateVecImag[indexInChunk]));
+
758  # endif
+
759  indexInChunk += 1;
+
760  }
+
761  totalIndex += 1;
+
762  }
+
763  }
+
764  fclose(fp);
+
765  copyStateToGPU(*qureg);
+
766 
+
767  // indicate success
+
768  return 1;
+
769 }
+
+

References Qureg::chunkId, copyStateToGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

+ +

Referenced by initStateFromSingleFile().

@@ -7964,17 +7964,17 @@

Definition at line 716 of file QuEST_gpu.cu.

-
717 {
-
718  int threadsPerCUDABlock, CUDABlocks;
-
719  threadsPerCUDABlock = 128;
-
720  CUDABlocks = ceil((qreal)(qureg->numAmpsPerChunk)/threadsPerCUDABlock);
-
721  statevec_initStateOfSingleQubitKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg->numAmpsPerChunk, qureg->deviceStateVec.real, qureg->deviceStateVec.imag, qubitId, outcome);
-
722 }
+

Definition at line 718 of file QuEST_gpu.cu.

+
719 {
+
720  int threadsPerCUDABlock, CUDABlocks;
+
721  threadsPerCUDABlock = 128;
+
722  CUDABlocks = ceil((qreal)(qureg->numAmpsPerChunk)/threadsPerCUDABlock);
+
723  statevec_initStateOfSingleQubitKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg->numAmpsPerChunk, qureg->deviceStateVec.real, qureg->deviceStateVec.imag, qubitId, outcome);
+
724 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

-

Referenced by initStateOfSingleQubit().

+

Referenced by initStateOfSingleQubit().

@@ -8022,24 +8022,24 @@

-

Definition at line 698 of file QuEST_gpu.cu.

-
698  {
-
699  long long int index;
-
700  int bit;
-
701 
-
702  index = blockIdx.x*blockDim.x + threadIdx.x;
-
703  if (index>=stateVecSize) return;
-
704 
-
705  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2);
-
706  bit = extractBit(qubitId, index);
-
707  if (bit==outcome) {
-
708  stateVecReal[index] = normFactor;
-
709  stateVecImag[index] = 0.0;
-
710  } else {
-
711  stateVecReal[index] = 0.0;
-
712  stateVecImag[index] = 0.0;
-
713  }
-
714 }
+

Definition at line 700 of file QuEST_gpu.cu.

+
700  {
+
701  long long int index;
+
702  int bit;
+
703 
+
704  index = blockIdx.x*blockDim.x + threadIdx.x;
+
705  if (index>=stateVecSize) return;
+
706 
+
707  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2);
+
708  bit = extractBit(qubitId, index);
+
709  if (bit==outcome) {
+
710  stateVecReal[index] = normFactor;
+
711  stateVecImag[index] = 0.0;
+
712  } else {
+
713  stateVecReal[index] = 0.0;
+
714  stateVecImag[index] = 0.0;
+
715  }
+
716 }

References extractBit(), and qreal.

@@ -8061,16 +8061,16 @@

-

Definition at line 618 of file QuEST_gpu.cu.

-
619 {
-
620  int threadsPerCUDABlock, CUDABlocks;
-
621  threadsPerCUDABlock = 128;
-
622  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
623  statevec_initZeroStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
624  qureg.numAmpsPerChunk,
-
625  qureg.deviceStateVec.real,
-
626  qureg.deviceStateVec.imag);
-
627 }
+

Definition at line 620 of file QuEST_gpu.cu.

+
621 {
+
622  int threadsPerCUDABlock, CUDABlocks;
+
623  threadsPerCUDABlock = 128;
+
624  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
625  statevec_initZeroStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
626  qureg.numAmpsPerChunk,
+
627  qureg.deviceStateVec.real,
+
628  qureg.deviceStateVec.imag);
+
629 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -8110,22 +8110,22 @@

-

Definition at line 602 of file QuEST_gpu.cu.

-
602  {
-
603  long long int index;
-
604 
-
605  // initialise the state to |0000..0000>
-
606  index = blockIdx.x*blockDim.x + threadIdx.x;
-
607  if (index>=stateVecSize) return;
-
608  stateVecReal[index] = 0.0;
-
609  stateVecImag[index] = 0.0;
-
610 
-
611  if (index==0){
-
612  // zero state |0000..0000> has probability 1
-
613  stateVecReal[0] = 1.0;
-
614  stateVecImag[0] = 0.0;
-
615  }
-
616 }
+

Definition at line 604 of file QuEST_gpu.cu.

+
604  {
+
605  long long int index;
+
606 
+
607  // initialise the state to |0000..0000>
+
608  index = blockIdx.x*blockDim.x + threadIdx.x;
+
609  if (index>=stateVecSize) return;
+
610  stateVecReal[index] = 0.0;
+
611  stateVecImag[index] = 0.0;
+
612 
+
613  if (index==0){
+
614  // zero state |0000..0000> has probability 1
+
615  stateVecReal[0] = 1.0;
+
616  stateVecImag[0] = 0.0;
+
617  }
+
618 }

@@ -8161,17 +8161,17 @@

-

Definition at line 1916 of file QuEST_gpu.cu.

-
1916  {
-
1917 
-
1918  int numThreadsPerBlock = 128;
-
1919  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
-
1920  statevec_multiControlledMultiQubitNotKernel<<<numBlocks, numThreadsPerBlock>>>(qureg, ctrlMask, targMask);
-
1921 }
+

Definition at line 1918 of file QuEST_gpu.cu.

+
1918  {
+
1919 
+
1920  int numThreadsPerBlock = 128;
+
1921  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
+
1922  statevec_multiControlledMultiQubitNotKernel<<<numBlocks, numThreadsPerBlock>>>(qureg, ctrlMask, targMask);
+
1923 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

+

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

@@ -8207,43 +8207,43 @@

-

Definition at line 1879 of file QuEST_gpu.cu.

-
1879  {
-
1880 
-
1881  qreal* stateRe = qureg.deviceStateVec.real;
-
1882  qreal* stateIm = qureg.deviceStateVec.imag;
-
1883 
-
1884  // althouugh each thread swaps/updates two amplitudes, we still invoke one thread per amp
-
1885  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
1886  if (ampInd >= qureg.numAmpsPerChunk)
-
1887  return;
-
1888 
-
1889  // modify amplitudes only if control qubits are 1 for this state
-
1890  if (ctrlMask && ((ctrlMask & ampInd) != ctrlMask))
-
1891  return;
-
1892 
-
1893  long long int mateInd = ampInd ^ targMask;
+

Definition at line 1881 of file QuEST_gpu.cu.

+
1881  {
+
1882 
+
1883  qreal* stateRe = qureg.deviceStateVec.real;
+
1884  qreal* stateIm = qureg.deviceStateVec.imag;
+
1885 
+
1886  // althouugh each thread swaps/updates two amplitudes, we still invoke one thread per amp
+
1887  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
1888  if (ampInd >= qureg.numAmpsPerChunk)
+
1889  return;
+
1890 
+
1891  // modify amplitudes only if control qubits are 1 for this state
+
1892  if (ctrlMask && ((ctrlMask & ampInd) != ctrlMask))
+
1893  return;
1894 
-
1895  // if the mate is lower index, another thread is handling it
-
1896  if (mateInd < ampInd)
-
1897  return;
-
1898 
-
1899  /* it may seem wasteful to spawn more threads than are needed, and abort
-
1900  * half of them due to the amp pairing above (and potentially abort
-
1901  * an exponential number due to ctrlMask). however, since we are moving
-
1902  * global memory directly in a potentially non-contiguous fashoin, this
-
1903  * method is likely to be memory bandwidth bottlenecked anyway
-
1904  */
-
1905 
-
1906  qreal mateRe = stateRe[mateInd];
-
1907  qreal mateIm = stateIm[mateInd];
-
1908 
-
1909  // swap amp with mate
-
1910  stateRe[mateInd] = stateRe[ampInd];
-
1911  stateIm[mateInd] = stateIm[ampInd];
-
1912  stateRe[ampInd] = mateRe;
-
1913  stateIm[ampInd] = mateIm;
-
1914 }
+
1895  long long int mateInd = ampInd ^ targMask;
+
1896 
+
1897  // if the mate is lower index, another thread is handling it
+
1898  if (mateInd < ampInd)
+
1899  return;
+
1900 
+
1901  /* it may seem wasteful to spawn more threads than are needed, and abort
+
1902  * half of them due to the amp pairing above (and potentially abort
+
1903  * an exponential number due to ctrlMask). however, since we are moving
+
1904  * global memory directly in a potentially non-contiguous fashoin, this
+
1905  * method is likely to be memory bandwidth bottlenecked anyway
+
1906  */
+
1907 
+
1908  qreal mateRe = stateRe[mateInd];
+
1909  qreal mateIm = stateIm[mateInd];
+
1910 
+
1911  // swap amp with mate
+
1912  stateRe[mateInd] = stateRe[ampInd];
+
1913  stateIm[mateInd] = stateIm[ampInd];
+
1914  stateRe[ampInd] = mateRe;
+
1915  stateIm[ampInd] = mateIm;
+
1916 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -8297,66 +8297,66 @@

Todo:
refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.
-

Definition at line 1037 of file QuEST_gpu.cu.

-
1038 {
-
1039  int threadsPerCUDABlock = 128;
-
1040  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>numTargs)/threadsPerCUDABlock);
-
1041 
-
1042  // allocate device space for global {targs} (length: numTargs) and populate
-
1043  int *d_targs;
-
1044  size_t targMemSize = numTargs * sizeof *d_targs;
-
1045  cudaMalloc(&d_targs, targMemSize);
-
1046  cudaMemcpy(d_targs, targs, targMemSize, cudaMemcpyHostToDevice);
-
1047 
-
1048  // flatten out the u.real and u.imag lists
-
1049  int uNumRows = (1 << u.numQubits);
-
1050  qreal* uReFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uReFlat);
-
1051  qreal* uImFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uImFlat);
-
1052  long long int i = 0;
-
1053  for (int r=0; r < uNumRows; r++)
-
1054  for (int c=0; c < uNumRows; c++) {
-
1055  uReFlat[i] = u.real[r][c];
-
1056  uImFlat[i] = u.imag[r][c];
-
1057  i++;
-
1058  }
-
1059 
-
1060  // allocate device space for global u.real and u.imag (flatten by concatenating rows) and populate
-
1061  qreal* d_uRe;
-
1062  qreal* d_uIm;
-
1063  size_t uMemSize = uNumRows*uNumRows * sizeof *d_uRe; // size of each of d_uRe and d_uIm
-
1064  cudaMalloc(&d_uRe, uMemSize);
-
1065  cudaMalloc(&d_uIm, uMemSize);
-
1066  cudaMemcpy(d_uRe, uReFlat, uMemSize, cudaMemcpyHostToDevice);
-
1067  cudaMemcpy(d_uIm, uImFlat, uMemSize, cudaMemcpyHostToDevice);
-
1068 
-
1069  // allocate device Wspace for thread-local {ampInds}, {reAmps}, {imAmps} (length: 1<<numTargs)
-
1070  long long int *d_ampInds;
-
1071  qreal *d_reAmps;
-
1072  qreal *d_imAmps;
-
1073  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
1074  int numTargAmps = uNumRows;
-
1075  cudaMalloc(&d_ampInds, numTargAmps*gridSize * sizeof *d_ampInds);
-
1076  cudaMalloc(&d_reAmps, numTargAmps*gridSize * sizeof *d_reAmps);
-
1077  cudaMalloc(&d_imAmps, numTargAmps*gridSize * sizeof *d_imAmps);
-
1078 
-
1079  // call kernel
-
1080  statevec_multiControlledMultiQubitUnitaryKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
1081  qureg, ctrlMask, d_targs, numTargs, d_uRe, d_uIm, d_ampInds, d_reAmps, d_imAmps, numTargAmps);
-
1082 
-
1083  // free kernel memory
-
1084  free(uReFlat);
-
1085  free(uImFlat);
-
1086  cudaFree(d_targs);
-
1087  cudaFree(d_uRe);
-
1088  cudaFree(d_uIm);
-
1089  cudaFree(d_ampInds);
-
1090  cudaFree(d_reAmps);
-
1091  cudaFree(d_imAmps);
-
1092 }
+

Definition at line 1039 of file QuEST_gpu.cu.

+
1040 {
+
1041  int threadsPerCUDABlock = 128;
+
1042  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>numTargs)/threadsPerCUDABlock);
+
1043 
+
1044  // allocate device space for global {targs} (length: numTargs) and populate
+
1045  int *d_targs;
+
1046  size_t targMemSize = numTargs * sizeof *d_targs;
+
1047  cudaMalloc(&d_targs, targMemSize);
+
1048  cudaMemcpy(d_targs, targs, targMemSize, cudaMemcpyHostToDevice);
+
1049 
+
1050  // flatten out the u.real and u.imag lists
+
1051  int uNumRows = (1 << u.numQubits);
+
1052  qreal* uReFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uReFlat);
+
1053  qreal* uImFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uImFlat);
+
1054  long long int i = 0;
+
1055  for (int r=0; r < uNumRows; r++)
+
1056  for (int c=0; c < uNumRows; c++) {
+
1057  uReFlat[i] = u.real[r][c];
+
1058  uImFlat[i] = u.imag[r][c];
+
1059  i++;
+
1060  }
+
1061 
+
1062  // allocate device space for global u.real and u.imag (flatten by concatenating rows) and populate
+
1063  qreal* d_uRe;
+
1064  qreal* d_uIm;
+
1065  size_t uMemSize = uNumRows*uNumRows * sizeof *d_uRe; // size of each of d_uRe and d_uIm
+
1066  cudaMalloc(&d_uRe, uMemSize);
+
1067  cudaMalloc(&d_uIm, uMemSize);
+
1068  cudaMemcpy(d_uRe, uReFlat, uMemSize, cudaMemcpyHostToDevice);
+
1069  cudaMemcpy(d_uIm, uImFlat, uMemSize, cudaMemcpyHostToDevice);
+
1070 
+
1071  // allocate device Wspace for thread-local {ampInds}, {reAmps}, {imAmps} (length: 1<<numTargs)
+
1072  long long int *d_ampInds;
+
1073  qreal *d_reAmps;
+
1074  qreal *d_imAmps;
+
1075  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
+
1076  int numTargAmps = uNumRows;
+
1077  cudaMalloc(&d_ampInds, numTargAmps*gridSize * sizeof *d_ampInds);
+
1078  cudaMalloc(&d_reAmps, numTargAmps*gridSize * sizeof *d_reAmps);
+
1079  cudaMalloc(&d_imAmps, numTargAmps*gridSize * sizeof *d_imAmps);
+
1080 
+
1081  // call kernel
+
1082  statevec_multiControlledMultiQubitUnitaryKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
1083  qureg, ctrlMask, d_targs, numTargs, d_uRe, d_uIm, d_ampInds, d_reAmps, d_imAmps, numTargAmps);
+
1084 
+
1085  // free kernel memory
+
1086  free(uReFlat);
+
1087  free(uImFlat);
+
1088  cudaFree(d_targs);
+
1089  cudaFree(d_uRe);
+
1090  cudaFree(d_uIm);
+
1091  cudaFree(d_ampInds);
+
1092  cudaFree(d_reAmps);
+
1093  cudaFree(d_imAmps);
+
1094 }

References ComplexMatrixN::imag, Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, and ComplexMatrixN::real.

-

Referenced by applyMultiControlledMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

+

Referenced by applyMultiControlledMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

@@ -8434,62 +8434,62 @@

-

Definition at line 978 of file QuEST_gpu.cu.

-
981 {
-
982 
-
983  // decide the amplitudes this thread will modify
-
984  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
985  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
986  if (thisTask>=numTasks) return;
-
987 
-
988  // find this task's start index (where all targs are 0)
-
989  long long int ind00 = insertZeroBits(thisTask, targs, numTargs);
-
990 
-
991  // this task only modifies amplitudes if control qubits are 1 for this state
-
992  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
993  return;
-
994 
-
995  qreal *reVec = qureg.deviceStateVec.real;
-
996  qreal *imVec = qureg.deviceStateVec.imag;
-
997 
-
998  /*
-
999  each thread needs:
-
1000  long long int ampInds[numAmps];
-
1001  qreal reAmps[numAmps];
-
1002  qreal imAmps[numAmps];
-
1003  but instead has access to shared arrays, with below stride and offset
-
1004  */
-
1005  size_t stride = gridDim.x*blockDim.x;
-
1006  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
1007 
-
1008  // determine the indices and record values of target amps
-
1009  long long int ind;
-
1010  for (int i=0; i < numTargAmps; i++) {
-
1011 
-
1012  // get global index of current target qubit assignment
-
1013  ind = ind00;
-
1014  for (int t=0; t < numTargs; t++)
-
1015  if (extractBit(t, i))
-
1016  ind = flipBit(ind, targs[t]);
-
1017 
-
1018  ampInds[i*stride+offset] = ind;
-
1019  reAmps [i*stride+offset] = reVec[ind];
-
1020  imAmps [i*stride+offset] = imVec[ind];
-
1021  }
-
1022 
-
1023  // update the amplitudes
-
1024  for (int r=0; r < numTargAmps; r++) {
-
1025  ind = ampInds[r*stride+offset];
-
1026  reVec[ind] = 0;
-
1027  imVec[ind] = 0;
-
1028  for (int c=0; c < numTargAmps; c++) {
-
1029  qreal uReElem = uRe[c + r*numTargAmps];
-
1030  qreal uImElem = uIm[c + r*numTargAmps];
-
1031  reVec[ind] += reAmps[c*stride+offset]*uReElem - imAmps[c*stride+offset]*uImElem;
-
1032  imVec[ind] += reAmps[c*stride+offset]*uImElem + imAmps[c*stride+offset]*uReElem;
-
1033  }
-
1034  }
-
1035 }
+

Definition at line 980 of file QuEST_gpu.cu.

+
983 {
+
984 
+
985  // decide the amplitudes this thread will modify
+
986  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
987  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
+
988  if (thisTask>=numTasks) return;
+
989 
+
990  // find this task's start index (where all targs are 0)
+
991  long long int ind00 = insertZeroBits(thisTask, targs, numTargs);
+
992 
+
993  // this task only modifies amplitudes if control qubits are 1 for this state
+
994  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
+
995  return;
+
996 
+
997  qreal *reVec = qureg.deviceStateVec.real;
+
998  qreal *imVec = qureg.deviceStateVec.imag;
+
999 
+
1000  /*
+
1001  each thread needs:
+
1002  long long int ampInds[numAmps];
+
1003  qreal reAmps[numAmps];
+
1004  qreal imAmps[numAmps];
+
1005  but instead has access to shared arrays, with below stride and offset
+
1006  */
+
1007  size_t stride = gridDim.x*blockDim.x;
+
1008  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
+
1009 
+
1010  // determine the indices and record values of target amps
+
1011  long long int ind;
+
1012  for (int i=0; i < numTargAmps; i++) {
+
1013 
+
1014  // get global index of current target qubit assignment
+
1015  ind = ind00;
+
1016  for (int t=0; t < numTargs; t++)
+
1017  if (extractBit(t, i))
+
1018  ind = flipBit(ind, targs[t]);
+
1019 
+
1020  ampInds[i*stride+offset] = ind;
+
1021  reAmps [i*stride+offset] = reVec[ind];
+
1022  imAmps [i*stride+offset] = imVec[ind];
+
1023  }
+
1024 
+
1025  // update the amplitudes
+
1026  for (int r=0; r < numTargAmps; r++) {
+
1027  ind = ampInds[r*stride+offset];
+
1028  reVec[ind] = 0;
+
1029  imVec[ind] = 0;
+
1030  for (int c=0; c < numTargAmps; c++) {
+
1031  qreal uReElem = uRe[c + r*numTargAmps];
+
1032  qreal uImElem = uIm[c + r*numTargAmps];
+
1033  reVec[ind] += reAmps[c*stride+offset]*uReElem - imAmps[c*stride+offset]*uImElem;
+
1034  imVec[ind] += reAmps[c*stride+offset]*uImElem + imAmps[c*stride+offset]*uReElem;
+
1035  }
+
1036  }
+
1037 }

References Qureg::deviceStateVec, extractBit(), flipBit(), insertZeroBits(), Qureg::numAmpsPerChunk, and qreal.

@@ -8533,20 +8533,20 @@

-

Definition at line 1619 of file QuEST_gpu.cu.

-
1620 {
-
1621  qreal cosAngle = cos(angle/2.0);
-
1622  qreal sinAngle = sin(angle/2.0);
-
1623 
-
1624  int threadsPerCUDABlock, CUDABlocks;
-
1625  threadsPerCUDABlock = 128;
-
1626  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1627  statevec_multiControlledMultiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, targMask, cosAngle, sinAngle);
-
1628 }
+

Definition at line 1621 of file QuEST_gpu.cu.

+
1622 {
+
1623  qreal cosAngle = cos(angle/2.0);
+
1624  qreal sinAngle = sin(angle/2.0);
+
1625 
+
1626  int threadsPerCUDABlock, CUDABlocks;
+
1627  threadsPerCUDABlock = 128;
+
1628  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1629  statevec_multiControlledMultiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, targMask, cosAngle, sinAngle);
+
1630 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by multiControlledMultiRotateZ(), and statevec_multiControlledMultiRotatePauli().

+

Referenced by multiControlledMultiRotateZ(), and statevec_multiControlledMultiRotatePauli().

@@ -8594,28 +8594,28 @@

-

Definition at line 1597 of file QuEST_gpu.cu.

-
1597  {
-
1598 
-
1599  long long int stateVecSize = qureg.numAmpsPerChunk;
-
1600  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
1601  if (index>=stateVecSize) return;
-
1602 
-
1603  // amplitudes corresponding to control qubits not all-in-one are unmodified
-
1604  if (ctrlMask && ((ctrlMask & index) != ctrlMask))
-
1605  return;
-
1606 
-
1607  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1608  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1609 
-
1610  // avoid warp divergence, setting fac = +- 1
-
1611  int fac = 1-2*getBitMaskParity(targMask & index);
-
1612  qreal stateReal = stateVecReal[index];
-
1613  qreal stateImag = stateVecImag[index];
-
1614 
-
1615  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
1616  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
1617 }
+

Definition at line 1599 of file QuEST_gpu.cu.

+
1599  {
+
1600 
+
1601  long long int stateVecSize = qureg.numAmpsPerChunk;
+
1602  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
1603  if (index>=stateVecSize) return;
+
1604 
+
1605  // amplitudes corresponding to control qubits not all-in-one are unmodified
+
1606  if (ctrlMask && ((ctrlMask & index) != ctrlMask))
+
1607  return;
+
1608 
+
1609  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1610  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1611 
+
1612  // avoid warp divergence, setting fac = +- 1
+
1613  int fac = 1-2*getBitMaskParity(targMask & index);
+
1614  qreal stateReal = stateVecReal[index];
+
1615  qreal stateImag = stateVecImag[index];
+
1616 
+
1617  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
1618  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
1619 }

References Qureg::deviceStateVec, getBitMaskParity(), Qureg::numAmpsPerChunk, and qreal.

@@ -8653,18 +8653,18 @@

-

Definition at line 1732 of file QuEST_gpu.cu.

-
1733 {
-
1734  int threadsPerCUDABlock, CUDABlocks;
-
1735  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1736  threadsPerCUDABlock = 128;
-
1737  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1738  statevec_multiControlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask);
-
1739 }
+

Definition at line 1734 of file QuEST_gpu.cu.

+
1735 {
+
1736  int threadsPerCUDABlock, CUDABlocks;
+
1737  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
1738  threadsPerCUDABlock = 128;
+
1739  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1740  statevec_multiControlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask);
+
1741 }

References getQubitBitMask(), Qureg::numAmpsPerChunk, and qreal.

-

Referenced by multiControlledPhaseFlip().

+

Referenced by multiControlledPhaseFlip().

@@ -8694,23 +8694,23 @@

-

Definition at line 1714 of file QuEST_gpu.cu.

-
1715 {
-
1716  long long int index;
-
1717  long long int stateVecSize;
-
1718 
-
1719  stateVecSize = qureg.numAmpsPerChunk;
-
1720  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1721  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1722 
-
1723  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1724  if (index>=stateVecSize) return;
-
1725 
-
1726  if (mask == (mask & index) ){
-
1727  stateVecReal [index] = - stateVecReal [index];
-
1728  stateVecImag [index] = - stateVecImag [index];
-
1729  }
-
1730 }
+

Definition at line 1716 of file QuEST_gpu.cu.

+
1717 {
+
1718  long long int index;
+
1719  long long int stateVecSize;
+
1720 
+
1721  stateVecSize = qureg.numAmpsPerChunk;
+
1722  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1723  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1724 
+
1725  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1726  if (index>=stateVecSize) return;
+
1727 
+
1728  if (mask == (mask & index) ){
+
1729  stateVecReal [index] = - stateVecReal [index];
+
1730  stateVecImag [index] = - stateVecImag [index];
+
1731  }
+
1732 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -8754,22 +8754,22 @@

-

Definition at line 1556 of file QuEST_gpu.cu.

-
1557 {
-
1558  qreal cosAngle = cos(angle);
-
1559  qreal sinAngle = sin(angle);
-
1560 
-
1561  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1562 
-
1563  int threadsPerCUDABlock, CUDABlocks;
-
1564  threadsPerCUDABlock = 128;
-
1565  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1566  statevec_multiControlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1567 }
+

Definition at line 1558 of file QuEST_gpu.cu.

+
1559 {
+
1560  qreal cosAngle = cos(angle);
+
1561  qreal sinAngle = sin(angle);
+
1562 
+
1563  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
1564 
+
1565  int threadsPerCUDABlock, CUDABlocks;
+
1566  threadsPerCUDABlock = 128;
+
1567  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1568  statevec_multiControlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
+
1569 }

References getQubitBitMask(), Qureg::numAmpsPerChunk, and qreal.

-

Referenced by multiControlledPhaseShift().

+

Referenced by multiControlledPhaseShift().

@@ -8811,26 +8811,26 @@

-

Definition at line 1536 of file QuEST_gpu.cu.

-
1536  {
-
1537  qreal stateRealLo, stateImagLo;
-
1538  long long int index;
-
1539  long long int stateVecSize;
-
1540 
-
1541  stateVecSize = qureg.numAmpsPerChunk;
-
1542  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1543  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1544 
-
1545  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1546  if (index>=stateVecSize) return;
-
1547 
-
1548  if (mask == (mask & index) ){
-
1549  stateRealLo = stateVecReal[index];
-
1550  stateImagLo = stateVecImag[index];
-
1551  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1552  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1553  }
-
1554 }
+

Definition at line 1538 of file QuEST_gpu.cu.

+
1538  {
+
1539  qreal stateRealLo, stateImagLo;
+
1540  long long int index;
+
1541  long long int stateVecSize;
+
1542 
+
1543  stateVecSize = qureg.numAmpsPerChunk;
+
1544  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1545  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1546 
+
1547  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1548  if (index>=stateVecSize) return;
+
1549 
+
1550  if (mask == (mask & index) ){
+
1551  stateRealLo = stateVecReal[index];
+
1552  stateImagLo = stateVecImag[index];
+
1553  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
1554  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
1555  }
+
1556 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -8886,16 +8886,16 @@

the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

-

Definition at line 1170 of file QuEST_gpu.cu.

-
1171 {
-
1172  int threadsPerCUDABlock = 128;
-
1173  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock); // one kernel eval for every 4 amplitudes
-
1174  statevec_multiControlledTwoQubitUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, q1, q2, argifyMatrix4(u));
-
1175 }
+

Definition at line 1172 of file QuEST_gpu.cu.

+
1173 {
+
1174  int threadsPerCUDABlock = 128;
+
1175  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock); // one kernel eval for every 4 amplitudes
+
1176  statevec_multiControlledTwoQubitUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, q1, q2, argifyMatrix4(u));
+
1177 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

+

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

@@ -8943,82 +8943,82 @@

-

Definition at line 1094 of file QuEST_gpu.cu.

-
1094  {
-
1095 
-
1096  // decide the 4 amplitudes this thread will modify
-
1097  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1098  long long int numTasks = qureg.numAmpsPerChunk >> 2; // kernel called on every 1 in 4 amplitudes
-
1099  if (thisTask>=numTasks) return;
-
1100 
-
1101  qreal *reVec = qureg.deviceStateVec.real;
-
1102  qreal *imVec = qureg.deviceStateVec.imag;
-
1103 
-
1104  // find indices of amplitudes to modify (treat q1 as the least significant bit)
-
1105  long long int ind00, ind01, ind10, ind11;
-
1106  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1107 
-
1108  // modify only if control qubits are 1 for this state
-
1109  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
1110  return;
-
1111 
-
1112  ind01 = flipBit(ind00, q1);
-
1113  ind10 = flipBit(ind00, q2);
-
1114  ind11 = flipBit(ind01, q2);
-
1115 
-
1116  // extract statevec amplitudes
-
1117  qreal re00, re01, re10, re11;
-
1118  qreal im00, im01, im10, im11;
-
1119  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1120  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1121  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1122  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1123 
-
1124  // apply u * {amp00, amp01, amp10, amp11}
-
1125  reVec[ind00] =
-
1126  u.r0c0.real*re00 - u.r0c0.imag*im00 +
-
1127  u.r0c1.real*re01 - u.r0c1.imag*im01 +
-
1128  u.r0c2.real*re10 - u.r0c2.imag*im10 +
-
1129  u.r0c3.real*re11 - u.r0c3.imag*im11;
-
1130  imVec[ind00] =
-
1131  u.r0c0.imag*re00 + u.r0c0.real*im00 +
-
1132  u.r0c1.imag*re01 + u.r0c1.real*im01 +
-
1133  u.r0c2.imag*re10 + u.r0c2.real*im10 +
-
1134  u.r0c3.imag*re11 + u.r0c3.real*im11;
-
1135 
-
1136  reVec[ind01] =
-
1137  u.r1c0.real*re00 - u.r1c0.imag*im00 +
-
1138  u.r1c1.real*re01 - u.r1c1.imag*im01 +
-
1139  u.r1c2.real*re10 - u.r1c2.imag*im10 +
-
1140  u.r1c3.real*re11 - u.r1c3.imag*im11;
-
1141  imVec[ind01] =
-
1142  u.r1c0.imag*re00 + u.r1c0.real*im00 +
-
1143  u.r1c1.imag*re01 + u.r1c1.real*im01 +
-
1144  u.r1c2.imag*re10 + u.r1c2.real*im10 +
-
1145  u.r1c3.imag*re11 + u.r1c3.real*im11;
-
1146 
-
1147  reVec[ind10] =
-
1148  u.r2c0.real*re00 - u.r2c0.imag*im00 +
-
1149  u.r2c1.real*re01 - u.r2c1.imag*im01 +
-
1150  u.r2c2.real*re10 - u.r2c2.imag*im10 +
-
1151  u.r2c3.real*re11 - u.r2c3.imag*im11;
-
1152  imVec[ind10] =
-
1153  u.r2c0.imag*re00 + u.r2c0.real*im00 +
-
1154  u.r2c1.imag*re01 + u.r2c1.real*im01 +
-
1155  u.r2c2.imag*re10 + u.r2c2.real*im10 +
-
1156  u.r2c3.imag*re11 + u.r2c3.real*im11;
-
1157 
-
1158  reVec[ind11] =
-
1159  u.r3c0.real*re00 - u.r3c0.imag*im00 +
-
1160  u.r3c1.real*re01 - u.r3c1.imag*im01 +
-
1161  u.r3c2.real*re10 - u.r3c2.imag*im10 +
-
1162  u.r3c3.real*re11 - u.r3c3.imag*im11;
-
1163  imVec[ind11] =
-
1164  u.r3c0.imag*re00 + u.r3c0.real*im00 +
-
1165  u.r3c1.imag*re01 + u.r3c1.real*im01 +
-
1166  u.r3c2.imag*re10 + u.r3c2.real*im10 +
-
1167  u.r3c3.imag*re11 + u.r3c3.real*im11;
-
1168 }
+

Definition at line 1096 of file QuEST_gpu.cu.

+
1096  {
+
1097 
+
1098  // decide the 4 amplitudes this thread will modify
+
1099  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1100  long long int numTasks = qureg.numAmpsPerChunk >> 2; // kernel called on every 1 in 4 amplitudes
+
1101  if (thisTask>=numTasks) return;
+
1102 
+
1103  qreal *reVec = qureg.deviceStateVec.real;
+
1104  qreal *imVec = qureg.deviceStateVec.imag;
+
1105 
+
1106  // find indices of amplitudes to modify (treat q1 as the least significant bit)
+
1107  long long int ind00, ind01, ind10, ind11;
+
1108  ind00 = insertTwoZeroBits(thisTask, q1, q2);
+
1109 
+
1110  // modify only if control qubits are 1 for this state
+
1111  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
+
1112  return;
+
1113 
+
1114  ind01 = flipBit(ind00, q1);
+
1115  ind10 = flipBit(ind00, q2);
+
1116  ind11 = flipBit(ind01, q2);
+
1117 
+
1118  // extract statevec amplitudes
+
1119  qreal re00, re01, re10, re11;
+
1120  qreal im00, im01, im10, im11;
+
1121  re00 = reVec[ind00]; im00 = imVec[ind00];
+
1122  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1123  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1124  re11 = reVec[ind11]; im11 = imVec[ind11];
+
1125 
+
1126  // apply u * {amp00, amp01, amp10, amp11}
+
1127  reVec[ind00] =
+
1128  u.r0c0.real*re00 - u.r0c0.imag*im00 +
+
1129  u.r0c1.real*re01 - u.r0c1.imag*im01 +
+
1130  u.r0c2.real*re10 - u.r0c2.imag*im10 +
+
1131  u.r0c3.real*re11 - u.r0c3.imag*im11;
+
1132  imVec[ind00] =
+
1133  u.r0c0.imag*re00 + u.r0c0.real*im00 +
+
1134  u.r0c1.imag*re01 + u.r0c1.real*im01 +
+
1135  u.r0c2.imag*re10 + u.r0c2.real*im10 +
+
1136  u.r0c3.imag*re11 + u.r0c3.real*im11;
+
1137 
+
1138  reVec[ind01] =
+
1139  u.r1c0.real*re00 - u.r1c0.imag*im00 +
+
1140  u.r1c1.real*re01 - u.r1c1.imag*im01 +
+
1141  u.r1c2.real*re10 - u.r1c2.imag*im10 +
+
1142  u.r1c3.real*re11 - u.r1c3.imag*im11;
+
1143  imVec[ind01] =
+
1144  u.r1c0.imag*re00 + u.r1c0.real*im00 +
+
1145  u.r1c1.imag*re01 + u.r1c1.real*im01 +
+
1146  u.r1c2.imag*re10 + u.r1c2.real*im10 +
+
1147  u.r1c3.imag*re11 + u.r1c3.real*im11;
+
1148 
+
1149  reVec[ind10] =
+
1150  u.r2c0.real*re00 - u.r2c0.imag*im00 +
+
1151  u.r2c1.real*re01 - u.r2c1.imag*im01 +
+
1152  u.r2c2.real*re10 - u.r2c2.imag*im10 +
+
1153  u.r2c3.real*re11 - u.r2c3.imag*im11;
+
1154  imVec[ind10] =
+
1155  u.r2c0.imag*re00 + u.r2c0.real*im00 +
+
1156  u.r2c1.imag*re01 + u.r2c1.real*im01 +
+
1157  u.r2c2.imag*re10 + u.r2c2.real*im10 +
+
1158  u.r2c3.imag*re11 + u.r2c3.real*im11;
+
1159 
+
1160  reVec[ind11] =
+
1161  u.r3c0.real*re00 - u.r3c0.imag*im00 +
+
1162  u.r3c1.real*re01 - u.r3c1.imag*im01 +
+
1163  u.r3c2.real*re10 - u.r3c2.imag*im10 +
+
1164  u.r3c3.real*re11 - u.r3c3.imag*im11;
+
1165  imVec[ind11] =
+
1166  u.r3c0.imag*re00 + u.r3c0.real*im00 +
+
1167  u.r3c1.imag*re01 + u.r3c1.real*im01 +
+
1168  u.r3c2.imag*re10 + u.r3c2.real*im10 +
+
1169  u.r3c3.imag*re11 + u.r3c3.real*im11;
+
1170 }

References Qureg::deviceStateVec, flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, and qreal.

@@ -9068,17 +9068,17 @@

-

Definition at line 1303 of file QuEST_gpu.cu.

-
1307  {
-
1308  int threadsPerCUDABlock = 128;
-
1309  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1310  statevec_multiControlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
1311  qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, argifyMatrix2(u));
-
1312 }
+

Definition at line 1305 of file QuEST_gpu.cu.

+
1309  {
+
1310  int threadsPerCUDABlock = 128;
+
1311  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1312  statevec_multiControlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
1313  qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, argifyMatrix2(u));
+
1314 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by multiControlledUnitary(), multiStateControlledUnitary(), and statevec_multiControlledMultiRotatePauli().

+

Referenced by multiControlledUnitary(), multiStateControlledUnitary(), and statevec_multiControlledMultiRotatePauli().

@@ -9127,61 +9127,61 @@

fix – no necessary for GPU version

-

Definition at line 1243 of file QuEST_gpu.cu.

-
1247  {
-
1248  // ----- sizes
-
1249  long long int sizeBlock, // size of blocks
-
1250  sizeHalfBlock; // size of blocks halved
-
1251  // ----- indices
-
1252  long long int thisBlock, // current block
-
1253  indexUp,indexLo; // current index and corresponding index in lower half block
-
1254 
-
1255  // ----- temp variables
-
1256  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1257  stateImagUp,stateImagLo; // (used in updates)
-
1258  // ----- temp variables
-
1259  long long int thisTask; // task based approach for expose loop with small granularity
-
1260  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1261 
-
1262 
-
1263  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1264  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1265 
-
1266  // ---------------------------------------------------------------- //
-
1267  // rotate //
+

Definition at line 1245 of file QuEST_gpu.cu.

+
1249  {
+
1250  // ----- sizes
+
1251  long long int sizeBlock, // size of blocks
+
1252  sizeHalfBlock; // size of blocks halved
+
1253  // ----- indices
+
1254  long long int thisBlock, // current block
+
1255  indexUp,indexLo; // current index and corresponding index in lower half block
+
1256 
+
1257  // ----- temp variables
+
1258  qreal stateRealUp,stateRealLo, // storage for previous state values
+
1259  stateImagUp,stateImagLo; // (used in updates)
+
1260  // ----- temp variables
+
1261  long long int thisTask; // task based approach for expose loop with small granularity
+
1262  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1263 
+
1264 
+
1265  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1266  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1267 
1268  // ---------------------------------------------------------------- //
-
1269 
-
1271  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1272  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1273 
-
1274  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1275  if (thisTask>=numTasks) return;
-
1276 
-
1277  thisBlock = thisTask / sizeHalfBlock;
-
1278  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1279  indexLo = indexUp + sizeHalfBlock;
-
1280 
-
1281  if (ctrlQubitsMask == (ctrlQubitsMask & (indexUp ^ ctrlFlipMask))) {
-
1282  // store current state vector values in temp variables
-
1283  stateRealUp = stateVecReal[indexUp];
-
1284  stateImagUp = stateVecImag[indexUp];
-
1285 
-
1286  stateRealLo = stateVecReal[indexLo];
-
1287  stateImagLo = stateVecImag[indexLo];
-
1288 
-
1289  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1290  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1291  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1292  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1293  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1294 
-
1295  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1296  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1297  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1298  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1299  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1300  }
-
1301 }
+
1269  // rotate //
+
1270  // ---------------------------------------------------------------- //
+
1271 
+
1273  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1274  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1275 
+
1276  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1277  if (thisTask>=numTasks) return;
+
1278 
+
1279  thisBlock = thisTask / sizeHalfBlock;
+
1280  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1281  indexLo = indexUp + sizeHalfBlock;
+
1282 
+
1283  if (ctrlQubitsMask == (ctrlQubitsMask & (indexUp ^ ctrlFlipMask))) {
+
1284  // store current state vector values in temp variables
+
1285  stateRealUp = stateVecReal[indexUp];
+
1286  stateImagUp = stateVecImag[indexUp];
+
1287 
+
1288  stateRealLo = stateVecReal[indexLo];
+
1289  stateImagLo = stateVecImag[indexLo];
+
1290 
+
1291  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
1292  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
+
1293  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
+
1294  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
+
1295  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
+
1296 
+
1297  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
1298  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
+
1299  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
+
1300  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
+
1301  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
+
1302  }
+
1303 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -9219,20 +9219,20 @@

-

Definition at line 1586 of file QuEST_gpu.cu.

-
1587 {
-
1588  qreal cosAngle = cos(angle/2.0);
-
1589  qreal sinAngle = sin(angle/2.0);
-
1590 
-
1591  int threadsPerCUDABlock, CUDABlocks;
-
1592  threadsPerCUDABlock = 128;
-
1593  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1594  statevec_multiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1595 }
+

Definition at line 1588 of file QuEST_gpu.cu.

+
1589 {
+
1590  qreal cosAngle = cos(angle/2.0);
+
1591  qreal sinAngle = sin(angle/2.0);
+
1592 
+
1593  int threadsPerCUDABlock, CUDABlocks;
+
1594  threadsPerCUDABlock = 128;
+
1595  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1596  statevec_multiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
+
1597 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

+

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

@@ -9274,23 +9274,23 @@

-

Definition at line 1569 of file QuEST_gpu.cu.

-
1569  {
-
1570 
-
1571  long long int stateVecSize = qureg.numAmpsPerChunk;
-
1572  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
1573  if (index>=stateVecSize) return;
-
1574 
-
1575  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1576  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1577 
-
1578  int fac = getBitMaskParity(mask & index)? -1 : 1;
-
1579  qreal stateReal = stateVecReal[index];
-
1580  qreal stateImag = stateVecImag[index];
-
1581 
-
1582  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
1583  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
1584 }
+

Definition at line 1571 of file QuEST_gpu.cu.

+
1571  {
+
1572 
+
1573  long long int stateVecSize = qureg.numAmpsPerChunk;
+
1574  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
1575  if (index>=stateVecSize) return;
+
1576 
+
1577  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1578  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1579 
+
1580  int fac = getBitMaskParity(mask & index)? -1 : 1;
+
1581  qreal stateReal = stateVecReal[index];
+
1582  qreal stateImag = stateVecImag[index];
+
1583 
+
1584  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
1585  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
1586 }

References Qureg::deviceStateVec, getBitMaskParity(), Qureg::numAmpsPerChunk, and qreal.

@@ -9322,17 +9322,17 @@

-

Definition at line 1358 of file QuEST_gpu.cu.

-
1359 {
-
1360  int threadsPerCUDABlock, CUDABlocks;
-
1361  threadsPerCUDABlock = 128;
-
1362  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1363  statevec_pauliXKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1364 }
+

Definition at line 1360 of file QuEST_gpu.cu.

+
1361 {
+
1362  int threadsPerCUDABlock, CUDABlocks;
+
1363  threadsPerCUDABlock = 128;
+
1364  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1365  statevec_pauliXKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
+
1366 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by pauliX(), and statevec_applyPauliProd().

+

Referenced by pauliX(), and statevec_applyPauliProd().

@@ -9363,49 +9363,49 @@

fix – no necessary for GPU version

-

Definition at line 1314 of file QuEST_gpu.cu.

-
1314  {
-
1315  // ----- sizes
-
1316  long long int sizeBlock, // size of blocks
-
1317  sizeHalfBlock; // size of blocks halved
-
1318  // ----- indices
-
1319  long long int thisBlock, // current block
-
1320  indexUp,indexLo; // current index and corresponding index in lower half block
-
1321 
-
1322  // ----- temp variables
-
1323  qreal stateRealUp, // storage for previous state values
-
1324  stateImagUp; // (used in updates)
-
1325  // ----- temp variables
-
1326  long long int thisTask; // task based approach for expose loop with small granularity
-
1327  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1328 
-
1329  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1330  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1331 
-
1332  // ---------------------------------------------------------------- //
-
1333  // rotate //
+

Definition at line 1316 of file QuEST_gpu.cu.

+
1316  {
+
1317  // ----- sizes
+
1318  long long int sizeBlock, // size of blocks
+
1319  sizeHalfBlock; // size of blocks halved
+
1320  // ----- indices
+
1321  long long int thisBlock, // current block
+
1322  indexUp,indexLo; // current index and corresponding index in lower half block
+
1323 
+
1324  // ----- temp variables
+
1325  qreal stateRealUp, // storage for previous state values
+
1326  stateImagUp; // (used in updates)
+
1327  // ----- temp variables
+
1328  long long int thisTask; // task based approach for expose loop with small granularity
+
1329  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1330 
+
1331  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1332  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1333 
1334  // ---------------------------------------------------------------- //
-
1335 
-
1337  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1338  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1339 
-
1340  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1341  if (thisTask>=numTasks) return;
-
1342 
-
1343  thisBlock = thisTask / sizeHalfBlock;
-
1344  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1345  indexLo = indexUp + sizeHalfBlock;
-
1346 
-
1347  // store current state vector values in temp variables
-
1348  stateRealUp = stateVecReal[indexUp];
-
1349  stateImagUp = stateVecImag[indexUp];
-
1350 
-
1351  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1352  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1353 
-
1354  stateVecReal[indexLo] = stateRealUp;
-
1355  stateVecImag[indexLo] = stateImagUp;
-
1356 }
+
1335  // rotate //
+
1336  // ---------------------------------------------------------------- //
+
1337 
+
1339  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1340  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1341 
+
1342  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1343  if (thisTask>=numTasks) return;
+
1344 
+
1345  thisBlock = thisTask / sizeHalfBlock;
+
1346  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1347  indexLo = indexUp + sizeHalfBlock;
+
1348 
+
1349  // store current state vector values in temp variables
+
1350  stateRealUp = stateVecReal[indexUp];
+
1351  stateImagUp = stateVecImag[indexUp];
+
1352 
+
1353  stateVecReal[indexUp] = stateVecReal[indexLo];
+
1354  stateVecImag[indexUp] = stateVecImag[indexLo];
+
1355 
+
1356  stateVecReal[indexLo] = stateRealUp;
+
1357  stateVecImag[indexLo] = stateImagUp;
+
1358 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -9437,17 +9437,17 @@

-

Definition at line 1391 of file QuEST_gpu.cu.

-
1392 {
-
1393  int threadsPerCUDABlock, CUDABlocks;
-
1394  threadsPerCUDABlock = 128;
-
1395  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1396  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, 1);
-
1397 }
+

Definition at line 1393 of file QuEST_gpu.cu.

+
1394 {
+
1395  int threadsPerCUDABlock, CUDABlocks;
+
1396  threadsPerCUDABlock = 128;
+
1397  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1398  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, 1);
+
1399 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by pauliY(), and statevec_applyPauliProd().

+

Referenced by pauliY(), and statevec_applyPauliProd().

@@ -9477,17 +9477,17 @@

-

Definition at line 1399 of file QuEST_gpu.cu.

-
1400 {
-
1401  int threadsPerCUDABlock, CUDABlocks;
-
1402  threadsPerCUDABlock = 128;
-
1403  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1404  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, -1);
-
1405 }
+

Definition at line 1401 of file QuEST_gpu.cu.

+
1402 {
+
1403  int threadsPerCUDABlock, CUDABlocks;
+
1404  threadsPerCUDABlock = 128;
+
1405  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1406  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, -1);
+
1407 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by pauliY().

+

Referenced by pauliY().

@@ -9523,31 +9523,31 @@

-

Definition at line 1366 of file QuEST_gpu.cu.

-
1366  {
-
1367 
-
1368  long long int sizeHalfBlock = 1LL << targetQubit;
-
1369  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1370  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1371  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1372  if (thisTask>=numTasks) return;
-
1373 
-
1374  long long int thisBlock = thisTask / sizeHalfBlock;
-
1375  long long int indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1376  long long int indexLo = indexUp + sizeHalfBlock;
-
1377  qreal stateRealUp, stateImagUp;
-
1378 
-
1379  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1380  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1381  stateRealUp = stateVecReal[indexUp];
-
1382  stateImagUp = stateVecImag[indexUp];
-
1383 
-
1384  // update under +-{{0, -i}, {i, 0}}
-
1385  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1386  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1387  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1388  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1389 }
+

Definition at line 1368 of file QuEST_gpu.cu.

+
1368  {
+
1369 
+
1370  long long int sizeHalfBlock = 1LL << targetQubit;
+
1371  long long int sizeBlock = 2LL * sizeHalfBlock;
+
1372  long long int numTasks = qureg.numAmpsPerChunk >> 1;
+
1373  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1374  if (thisTask>=numTasks) return;
+
1375 
+
1376  long long int thisBlock = thisTask / sizeHalfBlock;
+
1377  long long int indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1378  long long int indexLo = indexUp + sizeHalfBlock;
+
1379  qreal stateRealUp, stateImagUp;
+
1380 
+
1381  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1382  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1383  stateRealUp = stateVecReal[indexUp];
+
1384  stateImagUp = stateVecImag[indexUp];
+
1385 
+
1386  // update under +-{{0, -i}, {i, 0}}
+
1387  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
1388  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
1389  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
1390  stateVecImag[indexLo] = conjFac * stateRealUp;
+
1391 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -9585,20 +9585,20 @@

-

Definition at line 1489 of file QuEST_gpu.cu.

-
1490 {
-
1491  qreal cosAngle = term.real;
-
1492  qreal sinAngle = term.imag;
-
1493 
-
1494  int threadsPerCUDABlock, CUDABlocks;
-
1495  threadsPerCUDABlock = 128;
-
1496  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1497  statevec_phaseShiftByTermKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, cosAngle, sinAngle);
-
1498 }
+

Definition at line 1491 of file QuEST_gpu.cu.

+
1492 {
+
1493  qreal cosAngle = term.real;
+
1494  qreal sinAngle = term.imag;
+
1495 
+
1496  int threadsPerCUDABlock, CUDABlocks;
+
1497  threadsPerCUDABlock = 128;
+
1498  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1499  statevec_phaseShiftByTermKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, cosAngle, sinAngle);
+
1500 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

-

Referenced by statevec_pauliZ(), statevec_phaseShift(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), and statevec_tGateConj().

+

Referenced by statevec_pauliZ(), statevec_phaseShift(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), and statevec_tGateConj().

@@ -9640,34 +9640,34 @@

-

Definition at line 1461 of file QuEST_gpu.cu.

-
1461  {
-
1462 
-
1463  long long int sizeBlock, sizeHalfBlock;
-
1464  long long int thisBlock, indexUp,indexLo;
-
1465 
-
1466  qreal stateRealLo, stateImagLo;
-
1467  long long int thisTask;
-
1468  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1469 
-
1470  sizeHalfBlock = 1LL << targetQubit;
-
1471  sizeBlock = 2LL * sizeHalfBlock;
-
1472 
-
1473  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1474  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1475 
-
1476  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1477  if (thisTask>=numTasks) return;
-
1478  thisBlock = thisTask / sizeHalfBlock;
-
1479  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1480  indexLo = indexUp + sizeHalfBlock;
-
1481 
-
1482  stateRealLo = stateVecReal[indexLo];
-
1483  stateImagLo = stateVecImag[indexLo];
-
1484 
-
1485  stateVecReal[indexLo] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1486  stateVecImag[indexLo] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1487 }
+

Definition at line 1463 of file QuEST_gpu.cu.

+
1463  {
+
1464 
+
1465  long long int sizeBlock, sizeHalfBlock;
+
1466  long long int thisBlock, indexUp,indexLo;
+
1467 
+
1468  qreal stateRealLo, stateImagLo;
+
1469  long long int thisTask;
+
1470  long long int numTasks = qureg.numAmpsPerChunk >> 1;
+
1471 
+
1472  sizeHalfBlock = 1LL << targetQubit;
+
1473  sizeBlock = 2LL * sizeHalfBlock;
+
1474 
+
1475  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1476  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1477 
+
1478  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1479  if (thisTask>=numTasks) return;
+
1480  thisBlock = thisTask / sizeHalfBlock;
+
1481  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1482  indexLo = indexUp + sizeHalfBlock;
+
1483 
+
1484  stateRealLo = stateVecReal[indexLo];
+
1485  stateImagLo = stateVecImag[indexLo];
+
1486 
+
1487  stateVecReal[indexLo] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
1488  stateVecImag[indexLo] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
1489 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -9708,36 +9708,36 @@

Definition at line 541 of file QuEST_gpu.cu.

-
541  {
-
542  long long int index;
-
543  int rank;
-
544  copyStateFromGPU(qureg);
-
545  if (qureg.numQubitsInStateVec<=5){
-
546  for (rank=0; rank<qureg.numChunks; rank++){
-
547  if (qureg.chunkId==rank){
-
548  if (reportRank) {
-
549  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
550  //printf("\trank, index, real, imag\n");
-
551  printf("real, imag\n");
-
552  } else if (rank==0) {
-
553  printf("Reporting state [\n");
-
554  printf("real, imag\n");
-
555  }
-
556 
-
557  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
558  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
559  }
-
560  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
561  }
-
562  syncQuESTEnv(env);
-
563  }
-
564  }
-
565 }
-
-

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

- -

Referenced by reportStateToScreen().

+

Definition at line 543 of file QuEST_gpu.cu.

+
543  {
+
544  long long int index;
+
545  int rank;
+
546  copyStateFromGPU(qureg);
+
547  if (qureg.numQubitsInStateVec<=5){
+
548  for (rank=0; rank<qureg.numChunks; rank++){
+
549  if (qureg.chunkId==rank){
+
550  if (reportRank) {
+
551  printf("Reporting state from rank %d [\n", qureg.chunkId);
+
552  //printf("\trank, index, real, imag\n");
+
553  printf("real, imag\n");
+
554  } else if (rank==0) {
+
555  printf("Reporting state [\n");
+
556  printf("real, imag\n");
+
557  }
+
558 
+
559  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
560  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
561  }
+
562  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
+
563  }
+
564  syncQuESTEnv(env);
+
565  }
+
566  }
+
567 }
+
+

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

+ +

Referenced by reportStateToScreen().

@@ -9803,7 +9803,7 @@

References Qureg::deviceStateVec.

-

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

+

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

@@ -9857,22 +9857,22 @@

-

Definition at line 3173 of file QuEST_gpu.cu.

-
3173  {
-
3174 
-
3175  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
+

Definition at line 3175 of file QuEST_gpu.cu.

+
3175  {
3176 
-
3177  int threadsPerCUDABlock, CUDABlocks;
-
3178  threadsPerCUDABlock = 128;
-
3179  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3180  statevec_setWeightedQuregKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3181  fac1, qureg1, fac2, qureg2, facOut, out
-
3182  );
-
3183 }
+
3177  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
+
3178 
+
3179  int threadsPerCUDABlock, CUDABlocks;
+
3180  threadsPerCUDABlock = 128;
+
3181  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3182  statevec_setWeightedQuregKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3183  fac1, qureg1, fac2, qureg2, facOut, out
+
3184  );
+
3185 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

+

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

@@ -9926,38 +9926,38 @@

-

Definition at line 3141 of file QuEST_gpu.cu.

-
3141  {
-
3142 
-
3143  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3144  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
-
3145  if (ampInd >= numAmpsToVisit) return;
-
3146 
-
3147  qreal *vecRe1 = qureg1.deviceStateVec.real;
-
3148  qreal *vecIm1 = qureg1.deviceStateVec.imag;
-
3149  qreal *vecRe2 = qureg2.deviceStateVec.real;
-
3150  qreal *vecIm2 = qureg2.deviceStateVec.imag;
-
3151  qreal *vecReOut = out.deviceStateVec.real;
-
3152  qreal *vecImOut = out.deviceStateVec.imag;
-
3153 
-
3154  qreal facRe1 = fac1.real;
-
3155  qreal facIm1 = fac1.imag;
-
3156  qreal facRe2 = fac2.real;
-
3157  qreal facIm2 = fac2.imag;
-
3158  qreal facReOut = facOut.real;
-
3159  qreal facImOut = facOut.imag;
-
3160 
-
3161  qreal re1,im1, re2,im2, reOut,imOut;
-
3162  long long int index = ampInd;
-
3163 
-
3164  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3165  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3166  reOut = vecReOut[index];
-
3167  imOut = vecImOut[index];
-
3168 
-
3169  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
3170  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
3171 }
+

Definition at line 3143 of file QuEST_gpu.cu.

+
3143  {
+
3144 
+
3145  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3146  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
+
3147  if (ampInd >= numAmpsToVisit) return;
+
3148 
+
3149  qreal *vecRe1 = qureg1.deviceStateVec.real;
+
3150  qreal *vecIm1 = qureg1.deviceStateVec.imag;
+
3151  qreal *vecRe2 = qureg2.deviceStateVec.real;
+
3152  qreal *vecIm2 = qureg2.deviceStateVec.imag;
+
3153  qreal *vecReOut = out.deviceStateVec.real;
+
3154  qreal *vecImOut = out.deviceStateVec.imag;
+
3155 
+
3156  qreal facRe1 = fac1.real;
+
3157  qreal facIm1 = fac1.imag;
+
3158  qreal facRe2 = fac2.real;
+
3159  qreal facIm2 = fac2.imag;
+
3160  qreal facReOut = facOut.real;
+
3161  qreal facImOut = facOut.imag;
+
3162 
+
3163  qreal re1,im1, re2,im2, reOut,imOut;
+
3164  long long int index = ampInd;
+
3165 
+
3166  re1 = vecRe1[index]; im1 = vecIm1[index];
+
3167  re2 = vecRe2[index]; im2 = vecIm2[index];
+
3168  reOut = vecReOut[index];
+
3169  imOut = vecImOut[index];
+
3170 
+
3171  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
+
3172  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
+
3173 }

References Qureg::deviceStateVec, Complex::imag, Qureg::numAmpsPerChunk, qreal, and Complex::real.

@@ -9995,17 +9995,17 @@

-

Definition at line 1767 of file QuEST_gpu.cu.

-
1768 {
-
1769  int threadsPerCUDABlock, CUDABlocks;
-
1770  threadsPerCUDABlock = 128;
-
1771  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock);
-
1772  statevec_swapQubitAmpsKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, qb1, qb2);
-
1773 }
+

Definition at line 1769 of file QuEST_gpu.cu.

+
1770 {
+
1771  int threadsPerCUDABlock, CUDABlocks;
+
1772  threadsPerCUDABlock = 128;
+
1773  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock);
+
1774  statevec_swapQubitAmpsKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, qb1, qb2);
+
1775 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by agnostic_applyQFT(), and swapGate().

+

Referenced by agnostic_applyQFT(), and swapGate().

@@ -10041,32 +10041,32 @@

-

Definition at line 1741 of file QuEST_gpu.cu.

-
1741  {
-
1742 
-
1743  qreal *reVec = qureg.deviceStateVec.real;
-
1744  qreal *imVec = qureg.deviceStateVec.imag;
-
1745 
-
1746  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
1747  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1748  if (thisTask>=numTasks) return;
-
1749 
-
1750  long long int ind00, ind01, ind10;
-
1751  qreal re01, re10, im01, im10;
-
1752 
-
1753  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
1754  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
1755  ind01 = flipBit(ind00, qb1);
-
1756  ind10 = flipBit(ind00, qb2);
-
1757 
-
1758  // extract statevec amplitudes
-
1759  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1760  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1761 
-
1762  // swap 01 and 10 amps
-
1763  reVec[ind01] = re10; reVec[ind10] = re01;
-
1764  imVec[ind01] = im10; imVec[ind10] = im01;
-
1765 }
+

Definition at line 1743 of file QuEST_gpu.cu.

+
1743  {
+
1744 
+
1745  qreal *reVec = qureg.deviceStateVec.real;
+
1746  qreal *imVec = qureg.deviceStateVec.imag;
+
1747 
+
1748  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
+
1749  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1750  if (thisTask>=numTasks) return;
+
1751 
+
1752  long long int ind00, ind01, ind10;
+
1753  qreal re01, re10, im01, im10;
+
1754 
+
1755  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
+
1756  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
+
1757  ind01 = flipBit(ind00, qb1);
+
1758  ind10 = flipBit(ind00, qb2);
+
1759 
+
1760  // extract statevec amplitudes
+
1761  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1762  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1763 
+
1764  // swap 01 and 10 amps
+
1765  reVec[ind01] = re10; reVec[ind10] = re01;
+
1766  imVec[ind01] = im10; imVec[ind10] = im01;
+
1767 }

References Qureg::deviceStateVec, flipBit(), insertTwoZeroBits(), Qureg::numAmpsPerChunk, and qreal.

@@ -10104,17 +10104,17 @@

-

Definition at line 970 of file QuEST_gpu.cu.

-
971 {
-
972  int threadsPerCUDABlock, CUDABlocks;
-
973  threadsPerCUDABlock = 128;
-
974  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
975  statevec_unitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, argifyMatrix2(u));
-
976 }
+

Definition at line 972 of file QuEST_gpu.cu.

+
973 {
+
974  int threadsPerCUDABlock, CUDABlocks;
+
975  threadsPerCUDABlock = 128;
+
976  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
977  statevec_unitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, argifyMatrix2(u));
+
978 }

References Qureg::numAmpsPerChunk, and qreal.

-

Referenced by applyMatrix2(), and unitary().

+

Referenced by applyMatrix2(), and unitary().

@@ -10151,58 +10151,58 @@

fix – no necessary for GPU version

-

Definition at line 917 of file QuEST_gpu.cu.

-
917  {
-
918  // ----- sizes
-
919  long long int sizeBlock, // size of blocks
-
920  sizeHalfBlock; // size of blocks halved
-
921  // ----- indices
-
922  long long int thisBlock, // current block
-
923  indexUp,indexLo; // current index and corresponding index in lower half block
-
924 
-
925  // ----- temp variables
-
926  qreal stateRealUp,stateRealLo, // storage for previous state values
-
927  stateImagUp,stateImagLo; // (used in updates)
-
928  // ----- temp variables
-
929  long long int thisTask; // task based approach for expose loop with small granularity
-
930  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
931 
-
932  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
933  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
934 
-
935  // ---------------------------------------------------------------- //
-
936  // rotate //
+

Definition at line 919 of file QuEST_gpu.cu.

+
919  {
+
920  // ----- sizes
+
921  long long int sizeBlock, // size of blocks
+
922  sizeHalfBlock; // size of blocks halved
+
923  // ----- indices
+
924  long long int thisBlock, // current block
+
925  indexUp,indexLo; // current index and corresponding index in lower half block
+
926 
+
927  // ----- temp variables
+
928  qreal stateRealUp,stateRealLo, // storage for previous state values
+
929  stateImagUp,stateImagLo; // (used in updates)
+
930  // ----- temp variables
+
931  long long int thisTask; // task based approach for expose loop with small granularity
+
932  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
933 
+
934  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
935  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
936 
937  // ---------------------------------------------------------------- //
-
938 
-
940  qreal *stateVecReal = qureg.deviceStateVec.real;
-
941  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
942 
-
943  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
944  if (thisTask>=numTasks) return;
-
945 
-
946  thisBlock = thisTask / sizeHalfBlock;
-
947  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
948  indexLo = indexUp + sizeHalfBlock;
-
949 
-
950  // store current state vector values in temp variables
-
951  stateRealUp = stateVecReal[indexUp];
-
952  stateImagUp = stateVecImag[indexUp];
-
953 
-
954  stateRealLo = stateVecReal[indexLo];
-
955  stateImagLo = stateVecImag[indexLo];
-
956 
-
957  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
958  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
959  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
960  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
961  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
962 
-
963  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
964  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
965  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
966  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
967  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
968 }
+
938  // rotate //
+
939  // ---------------------------------------------------------------- //
+
940 
+
942  qreal *stateVecReal = qureg.deviceStateVec.real;
+
943  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
944 
+
945  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
946  if (thisTask>=numTasks) return;
+
947 
+
948  thisBlock = thisTask / sizeHalfBlock;
+
949  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
950  indexLo = indexUp + sizeHalfBlock;
+
951 
+
952  // store current state vector values in temp variables
+
953  stateRealUp = stateVecReal[indexUp];
+
954  stateImagUp = stateVecImag[indexUp];
+
955 
+
956  stateRealLo = stateVecReal[indexLo];
+
957  stateImagLo = stateVecImag[indexLo];
+
958 
+
959  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
960  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
+
961  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
+
962  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
+
963  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
+
964 
+
965  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
966  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
+
967  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
+
968  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
+
969  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
+
970 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and qreal.

@@ -10234,41 +10234,41 @@

-

Definition at line 2055 of file QuEST_gpu.cu.

-

@ INVERSE_PRODUCT
Definition: QuEST.h:233
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
__device__ __host__ unsigned int log2Int(unsigned int x)
Definition: QuEST_gpu.cu:1923
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_gpu.cu:527
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
Definition: QuEST_gpu.cu:479
+
__device__ __host__ unsigned int log2Int(unsigned int x)
Definition: QuEST_gpu.cu:1925
+
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_gpu.cu:529
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
Definition: QuEST_gpu.cu:481
@ PAULI_Z
Definition: QuEST.h:96
@ DISTANCE
Definition: QuEST.h:234
-
int rank
Definition: QuEST.h:363
-
__global__ void copySharedReduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1949
-
void swapDouble(qreal **a, qreal **b)
Definition: QuEST_gpu.cu:2055
+
int rank
Definition: QuEST.h:364
+
__global__ void copySharedReduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1951
+
void swapDouble(qreal **a, qreal **b)
Definition: QuEST_gpu.cu:2057
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:304
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
qreal statevec_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2110
+
qreal statevec_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2112
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
ComplexArray deviceOperator
A copy of the elements stored persistently on the GPU.
Definition: QuEST.h:312
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:306
ComplexArray deviceStateVec
Storage for wavefunction amplitudes in the GPU version.
Definition: QuEST.h:346
@ NORM
Definition: QuEST.h:232
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac)
Definition: QuEST_gpu.cu:2877
+
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac)
Definition: QuEST_gpu.cu:2879
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
@ UNSIGNED
Definition: QuEST.h:269
@ INVERSE_DISTANCE
Definition: QuEST.h:234
@@ -10278,15 +10278,15 @@

int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
qreal densmatr_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2062
+
qreal densmatr_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2064
__forceinline__ __device__ int getBitMaskParity(long long int mask)
Definition: QuEST_gpu.cu:86
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_gpu.cu:517
+
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_gpu.cu:519
#define REDUCE_SHARED_SIZE
Definition: QuEST_gpu.cu:19
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
int numRanks
Definition: QuEST.h:364
+
int numRanks
Definition: QuEST.h:365
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
@@ -10296,7 +10296,7 @@

qreal ** real
Definition: QuEST.h:189
qreal * secondLevelReduction
Definition: QuEST.h:348
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_gpu.cu:2936
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_gpu.cu:2938
@ INVERSE_NORM
Definition: QuEST.h:232
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
qreal ** imag
Definition: QuEST.h:190
@@ -10305,13 +10305,13 @@

long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
int numQubits
Definition: QuEST.h:188
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_gpu.cu:2897
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_gpu.cu:2899
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
__device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1930
+
__device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1932
qreal imag
Definition: QuEST.h:106
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
Represents one complex number.
Definition: QuEST.h:103
diff --git a/docs/QuEST__gpu_8cu_source.html b/docs/QuEST__gpu_8cu_source.html index bfc8e12c3..8e40db12c 100644 --- a/docs/QuEST__gpu_8cu_source.html +++ b/docs/QuEST__gpu_8cu_source.html @@ -27,7 +27,7 @@ @@ -521,3695 +521,3704 @@
471  env.rank=0;
472  env.numRanks=1;
473 
- -
475 
-
476  return env;
-
477 }
-
478 
- -
480  cudaDeviceSynchronize();
-
481 }
-
482 
-
483 int syncQuESTSuccess(int successCode){
-
484  return successCode;
-
485 }
-
486 
- -
488  // MPI finalize goes here in MPI version. Call this function anyway for consistency
-
489 }
-
490 
- -
492  printf("EXECUTION ENVIRONMENT:\n");
-
493  printf("Running locally on one node with GPU\n");
-
494  printf("Number of ranks is %d\n", env.numRanks);
-
495 # ifdef _OPENMP
-
496  printf("OpenMP enabled\n");
-
497  printf("Number of threads available is %d\n", omp_get_max_threads());
-
498 # else
-
499  printf("OpenMP disabled\n");
-
500 # endif
-
501 }
-
502 
-
503 void getEnvironmentString(QuESTEnv env, char str[200]){
+
474  env.seeds = NULL;
+
475  env.numSeeds = 0;
+
476  seedQuESTDefault(env);
+
477 
+
478  return env;
+
479 }
+
480 
+ +
482  cudaDeviceSynchronize();
+
483 }
+
484 
+
485 int syncQuESTSuccess(int successCode){
+
486  return successCode;
+
487 }
+
488 
+ +
490  free(env.seeds);
+
491 }
+
492 
+ +
494  printf("EXECUTION ENVIRONMENT:\n");
+
495  printf("Running locally on one node with GPU\n");
+
496  printf("Number of ranks is %d\n", env.numRanks);
+
497 # ifdef _OPENMP
+
498  printf("OpenMP enabled\n");
+
499  printf("Number of threads available is %d\n", omp_get_max_threads());
+
500 # else
+
501  printf("OpenMP disabled\n");
+
502 # endif
+
503 }
504 
-
505  // OpenMP can be hybridised with GPU in future, so this check is safe and worthwhile
-
506  int ompStatus=0;
-
507  int numThreads=1;
-
508 # ifdef _OPENMP
-
509  ompStatus=1;
-
510  numThreads=omp_get_max_threads();
-
511 # endif
-
512 
-
513  // there is no reporting of CUDA cores/threads/blocks currently (since non-trivial)
-
514  sprintf(str, "CUDA=1 OpenMP=%d MPI=0 threads=%d ranks=1", ompStatus, numThreads);
-
515 }
-
516 
- -
518 {
-
519  if (DEBUG) printf("Copying data to GPU\n");
-
520  cudaMemcpy(qureg.deviceStateVec.real, qureg.stateVec.real,
-
521  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyHostToDevice);
-
522  cudaMemcpy(qureg.deviceStateVec.imag, qureg.stateVec.imag,
-
523  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyHostToDevice);
-
524  if (DEBUG) printf("Finished copying data to GPU\n");
-
525 }
-
526 
- -
528 {
-
529  cudaDeviceSynchronize();
-
530  if (DEBUG) printf("Copying data from GPU\n");
-
531  cudaMemcpy(qureg.stateVec.real, qureg.deviceStateVec.real,
-
532  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
-
533  cudaMemcpy(qureg.stateVec.imag, qureg.deviceStateVec.imag,
-
534  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
-
535  if (DEBUG) printf("Finished copying data from GPU\n");
-
536 }
-
537 
-
541 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank){
-
542  long long int index;
-
543  int rank;
-
544  copyStateFromGPU(qureg);
-
545  if (qureg.numQubitsInStateVec<=5){
-
546  for (rank=0; rank<qureg.numChunks; rank++){
-
547  if (qureg.chunkId==rank){
-
548  if (reportRank) {
-
549  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
550  //printf("\trank, index, real, imag\n");
-
551  printf("real, imag\n");
-
552  } else if (rank==0) {
-
553  printf("Reporting state [\n");
-
554  printf("real, imag\n");
-
555  }
-
556 
-
557  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
558  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
559  }
-
560  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
561  }
-
562  syncQuESTEnv(env);
-
563  }
-
564  }
-
565 }
-
566 
-
567 qreal statevec_getRealAmp(Qureg qureg, long long int index){
-
568  qreal el=0;
-
569  cudaMemcpy(&el, &(qureg.deviceStateVec.real[index]),
-
570  sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
-
571  return el;
-
572 }
-
573 
-
574 qreal statevec_getImagAmp(Qureg qureg, long long int index){
-
575  qreal el=0;
-
576  cudaMemcpy(&el, &(qureg.deviceStateVec.imag[index]),
-
577  sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
-
578  return el;
-
579 }
-
580 
-
581 __global__ void statevec_initBlankStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
582  long long int index;
-
583 
-
584  // initialise the statevector to be all-zeros
-
585  index = blockIdx.x*blockDim.x + threadIdx.x;
-
586  if (index>=stateVecSize) return;
-
587  stateVecReal[index] = 0.0;
-
588  stateVecImag[index] = 0.0;
-
589 }
-
590 
- -
592 {
-
593  int threadsPerCUDABlock, CUDABlocks;
-
594  threadsPerCUDABlock = 128;
-
595  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
596  statevec_initBlankStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
597  qureg.numAmpsPerChunk,
-
598  qureg.deviceStateVec.real,
-
599  qureg.deviceStateVec.imag);
-
600 }
-
601 
-
602 __global__ void statevec_initZeroStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
603  long long int index;
-
604 
-
605  // initialise the state to |0000..0000>
-
606  index = blockIdx.x*blockDim.x + threadIdx.x;
-
607  if (index>=stateVecSize) return;
-
608  stateVecReal[index] = 0.0;
-
609  stateVecImag[index] = 0.0;
-
610 
-
611  if (index==0){
-
612  // zero state |0000..0000> has probability 1
-
613  stateVecReal[0] = 1.0;
-
614  stateVecImag[0] = 0.0;
-
615  }
-
616 }
-
617 
- -
619 {
-
620  int threadsPerCUDABlock, CUDABlocks;
-
621  threadsPerCUDABlock = 128;
-
622  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
623  statevec_initZeroStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
624  qureg.numAmpsPerChunk,
-
625  qureg.deviceStateVec.real,
-
626  qureg.deviceStateVec.imag);
-
627 }
-
628 
-
629 __global__ void statevec_initPlusStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
630  long long int index;
-
631 
-
632  index = blockIdx.x*blockDim.x + threadIdx.x;
-
633  if (index>=stateVecSize) return;
-
634 
-
635  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
636  stateVecReal[index] = normFactor;
-
637  stateVecImag[index] = 0.0;
-
638 }
-
639 
- -
641 {
-
642  int threadsPerCUDABlock, CUDABlocks;
-
643  threadsPerCUDABlock = 128;
-
644  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
645  statevec_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
646  qureg.numAmpsPerChunk,
-
647  qureg.deviceStateVec.real,
-
648  qureg.deviceStateVec.imag);
-
649 }
-
650 
-
651 __global__ void statevec_initClassicalStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd){
-
652  long long int index;
-
653 
-
654  // initialise the state to |stateInd>
-
655  index = blockIdx.x*blockDim.x + threadIdx.x;
-
656  if (index>=stateVecSize) return;
-
657  stateVecReal[index] = 0.0;
-
658  stateVecImag[index] = 0.0;
-
659 
-
660  if (index==stateInd){
-
661  // classical state has probability 1
-
662  stateVecReal[stateInd] = 1.0;
-
663  stateVecImag[stateInd] = 0.0;
-
664  }
-
665 }
-
666 void statevec_initClassicalState(Qureg qureg, long long int stateInd)
-
667 {
-
668  int threadsPerCUDABlock, CUDABlocks;
-
669  threadsPerCUDABlock = 128;
-
670  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
671  statevec_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
672  qureg.numAmpsPerChunk,
-
673  qureg.deviceStateVec.real,
-
674  qureg.deviceStateVec.imag, stateInd);
-
675 }
-
676 
-
677 __global__ void statevec_initDebugStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
-
678  long long int index;
-
679 
-
680  index = blockIdx.x*blockDim.x + threadIdx.x;
-
681  if (index>=stateVecSize) return;
-
682 
-
683  stateVecReal[index] = (index*2.0)/10.0;
-
684  stateVecImag[index] = (index*2.0+1.0)/10.0;
-
685 }
-
686 
- -
688 {
-
689  int threadsPerCUDABlock, CUDABlocks;
-
690  threadsPerCUDABlock = 128;
-
691  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
692  statevec_initDebugStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
693  qureg.numAmpsPerChunk,
-
694  qureg.deviceStateVec.real,
-
695  qureg.deviceStateVec.imag);
-
696 }
-
697 
-
698 __global__ void statevec_initStateOfSingleQubitKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome){
-
699  long long int index;
-
700  int bit;
-
701 
-
702  index = blockIdx.x*blockDim.x + threadIdx.x;
-
703  if (index>=stateVecSize) return;
-
704 
-
705  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2);
-
706  bit = extractBit(qubitId, index);
-
707  if (bit==outcome) {
-
708  stateVecReal[index] = normFactor;
-
709  stateVecImag[index] = 0.0;
-
710  } else {
-
711  stateVecReal[index] = 0.0;
-
712  stateVecImag[index] = 0.0;
-
713  }
-
714 }
-
715 
-
716 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
-
717 {
-
718  int threadsPerCUDABlock, CUDABlocks;
-
719  threadsPerCUDABlock = 128;
-
720  CUDABlocks = ceil((qreal)(qureg->numAmpsPerChunk)/threadsPerCUDABlock);
-
721  statevec_initStateOfSingleQubitKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg->numAmpsPerChunk, qureg->deviceStateVec.real, qureg->deviceStateVec.imag, qubitId, outcome);
-
722 }
-
723 
-
724 // returns 1 if successful, else 0
-
725 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
-
726  long long int chunkSize, stateVecSize;
-
727  long long int indexInChunk, totalIndex;
-
728 
-
729  chunkSize = qureg->numAmpsPerChunk;
-
730  stateVecSize = chunkSize*qureg->numChunks;
-
731 
-
732  qreal *stateVecReal = qureg->stateVec.real;
-
733  qreal *stateVecImag = qureg->stateVec.imag;
-
734 
-
735  FILE *fp;
-
736  char line[200];
-
737 
-
738  fp = fopen(filename, "r");
-
739  if (fp == NULL)
-
740  return 0;
-
741 
-
742  indexInChunk = 0; totalIndex = 0;
-
743  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
744  if (line[0]!='#'){
-
745  int chunkId = totalIndex/chunkSize;
-
746  if (chunkId==qureg->chunkId){
-
747  # if QuEST_PREC==1
-
748  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
749  &(stateVecImag[indexInChunk]));
-
750  # elif QuEST_PREC==2
-
751  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
752  &(stateVecImag[indexInChunk]));
-
753  # elif QuEST_PREC==4
-
754  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
755  &(stateVecImag[indexInChunk]));
-
756  # endif
-
757  indexInChunk += 1;
-
758  }
-
759  totalIndex += 1;
-
760  }
-
761  }
-
762  fclose(fp);
-
763  copyStateToGPU(*qureg);
-
764 
-
765  // indicate success
-
766  return 1;
-
767 }
-
768 
-
769 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
-
770  qreal diff;
-
771  int chunkSize = mq1.numAmpsPerChunk;
-
772 
-
773  copyStateFromGPU(mq1);
-
774  copyStateFromGPU(mq2);
-
775 
-
776  for (int i=0; i<chunkSize; i++){
-
777  diff = mq1.stateVec.real[i] - mq2.stateVec.real[i];
-
778  if (diff<0) diff *= -1;
-
779  if (diff>precision) return 0;
-
780  diff = mq1.stateVec.imag[i] - mq2.stateVec.imag[i];
-
781  if (diff<0) diff *= -1;
-
782  if (diff>precision) return 0;
-
783  }
-
784  return 1;
-
785 }
-
786 
-
787 __global__ void statevec_compactUnitaryKernel (Qureg qureg, int rotQubit, Complex alpha, Complex beta){
-
788  // ----- sizes
-
789  long long int sizeBlock, // size of blocks
-
790  sizeHalfBlock; // size of blocks halved
-
791  // ----- indices
-
792  long long int thisBlock, // current block
-
793  indexUp,indexLo; // current index and corresponding index in lower half block
-
794 
-
795  // ----- temp variables
-
796  qreal stateRealUp,stateRealLo, // storage for previous state values
-
797  stateImagUp,stateImagLo; // (used in updates)
-
798  // ----- temp variables
-
799  long long int thisTask; // task based approach for expose loop with small granularity
-
800  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
801 
-
802  sizeHalfBlock = 1LL << rotQubit; // size of blocks halved
-
803  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
804 
-
805  // ---------------------------------------------------------------- //
-
806  // rotate //
+
505 void getEnvironmentString(QuESTEnv env, char str[200]){
+
506 
+
507  // OpenMP can be hybridised with GPU in future, so this check is safe and worthwhile
+
508  int ompStatus=0;
+
509  int numThreads=1;
+
510 # ifdef _OPENMP
+
511  ompStatus=1;
+
512  numThreads=omp_get_max_threads();
+
513 # endif
+
514 
+
515  // there is no reporting of CUDA cores/threads/blocks currently (since non-trivial)
+
516  sprintf(str, "CUDA=1 OpenMP=%d MPI=0 threads=%d ranks=1", ompStatus, numThreads);
+
517 }
+
518 
+ +
520 {
+
521  if (DEBUG) printf("Copying data to GPU\n");
+
522  cudaMemcpy(qureg.deviceStateVec.real, qureg.stateVec.real,
+
523  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyHostToDevice);
+
524  cudaMemcpy(qureg.deviceStateVec.imag, qureg.stateVec.imag,
+
525  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyHostToDevice);
+
526  if (DEBUG) printf("Finished copying data to GPU\n");
+
527 }
+
528 
+ +
530 {
+
531  cudaDeviceSynchronize();
+
532  if (DEBUG) printf("Copying data from GPU\n");
+
533  cudaMemcpy(qureg.stateVec.real, qureg.deviceStateVec.real,
+
534  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
+
535  cudaMemcpy(qureg.stateVec.imag, qureg.deviceStateVec.imag,
+
536  qureg.numAmpsPerChunk*sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
+
537  if (DEBUG) printf("Finished copying data from GPU\n");
+
538 }
+
539 
+
543 void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank){
+
544  long long int index;
+
545  int rank;
+
546  copyStateFromGPU(qureg);
+
547  if (qureg.numQubitsInStateVec<=5){
+
548  for (rank=0; rank<qureg.numChunks; rank++){
+
549  if (qureg.chunkId==rank){
+
550  if (reportRank) {
+
551  printf("Reporting state from rank %d [\n", qureg.chunkId);
+
552  //printf("\trank, index, real, imag\n");
+
553  printf("real, imag\n");
+
554  } else if (rank==0) {
+
555  printf("Reporting state [\n");
+
556  printf("real, imag\n");
+
557  }
+
558 
+
559  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
560  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
561  }
+
562  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
+
563  }
+
564  syncQuESTEnv(env);
+
565  }
+
566  }
+
567 }
+
568 
+
569 qreal statevec_getRealAmp(Qureg qureg, long long int index){
+
570  qreal el=0;
+
571  cudaMemcpy(&el, &(qureg.deviceStateVec.real[index]),
+
572  sizeof(*(qureg.deviceStateVec.real)), cudaMemcpyDeviceToHost);
+
573  return el;
+
574 }
+
575 
+
576 qreal statevec_getImagAmp(Qureg qureg, long long int index){
+
577  qreal el=0;
+
578  cudaMemcpy(&el, &(qureg.deviceStateVec.imag[index]),
+
579  sizeof(*(qureg.deviceStateVec.imag)), cudaMemcpyDeviceToHost);
+
580  return el;
+
581 }
+
582 
+
583 __global__ void statevec_initBlankStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
+
584  long long int index;
+
585 
+
586  // initialise the statevector to be all-zeros
+
587  index = blockIdx.x*blockDim.x + threadIdx.x;
+
588  if (index>=stateVecSize) return;
+
589  stateVecReal[index] = 0.0;
+
590  stateVecImag[index] = 0.0;
+
591 }
+
592 
+ +
594 {
+
595  int threadsPerCUDABlock, CUDABlocks;
+
596  threadsPerCUDABlock = 128;
+
597  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
598  statevec_initBlankStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
599  qureg.numAmpsPerChunk,
+
600  qureg.deviceStateVec.real,
+
601  qureg.deviceStateVec.imag);
+
602 }
+
603 
+
604 __global__ void statevec_initZeroStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
+
605  long long int index;
+
606 
+
607  // initialise the state to |0000..0000>
+
608  index = blockIdx.x*blockDim.x + threadIdx.x;
+
609  if (index>=stateVecSize) return;
+
610  stateVecReal[index] = 0.0;
+
611  stateVecImag[index] = 0.0;
+
612 
+
613  if (index==0){
+
614  // zero state |0000..0000> has probability 1
+
615  stateVecReal[0] = 1.0;
+
616  stateVecImag[0] = 0.0;
+
617  }
+
618 }
+
619 
+ +
621 {
+
622  int threadsPerCUDABlock, CUDABlocks;
+
623  threadsPerCUDABlock = 128;
+
624  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
625  statevec_initZeroStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
626  qureg.numAmpsPerChunk,
+
627  qureg.deviceStateVec.real,
+
628  qureg.deviceStateVec.imag);
+
629 }
+
630 
+
631 __global__ void statevec_initPlusStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
+
632  long long int index;
+
633 
+
634  index = blockIdx.x*blockDim.x + threadIdx.x;
+
635  if (index>=stateVecSize) return;
+
636 
+
637  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
+
638  stateVecReal[index] = normFactor;
+
639  stateVecImag[index] = 0.0;
+
640 }
+
641 
+ +
643 {
+
644  int threadsPerCUDABlock, CUDABlocks;
+
645  threadsPerCUDABlock = 128;
+
646  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
647  statevec_initPlusStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
648  qureg.numAmpsPerChunk,
+
649  qureg.deviceStateVec.real,
+
650  qureg.deviceStateVec.imag);
+
651 }
+
652 
+
653 __global__ void statevec_initClassicalStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd){
+
654  long long int index;
+
655 
+
656  // initialise the state to |stateInd>
+
657  index = blockIdx.x*blockDim.x + threadIdx.x;
+
658  if (index>=stateVecSize) return;
+
659  stateVecReal[index] = 0.0;
+
660  stateVecImag[index] = 0.0;
+
661 
+
662  if (index==stateInd){
+
663  // classical state has probability 1
+
664  stateVecReal[stateInd] = 1.0;
+
665  stateVecImag[stateInd] = 0.0;
+
666  }
+
667 }
+
668 void statevec_initClassicalState(Qureg qureg, long long int stateInd)
+
669 {
+
670  int threadsPerCUDABlock, CUDABlocks;
+
671  threadsPerCUDABlock = 128;
+
672  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
673  statevec_initClassicalStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
674  qureg.numAmpsPerChunk,
+
675  qureg.deviceStateVec.real,
+
676  qureg.deviceStateVec.imag, stateInd);
+
677 }
+
678 
+
679 __global__ void statevec_initDebugStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag){
+
680  long long int index;
+
681 
+
682  index = blockIdx.x*blockDim.x + threadIdx.x;
+
683  if (index>=stateVecSize) return;
+
684 
+
685  stateVecReal[index] = (index*2.0)/10.0;
+
686  stateVecImag[index] = (index*2.0+1.0)/10.0;
+
687 }
+
688 
+ +
690 {
+
691  int threadsPerCUDABlock, CUDABlocks;
+
692  threadsPerCUDABlock = 128;
+
693  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
694  statevec_initDebugStateKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
695  qureg.numAmpsPerChunk,
+
696  qureg.deviceStateVec.real,
+
697  qureg.deviceStateVec.imag);
+
698 }
+
699 
+
700 __global__ void statevec_initStateOfSingleQubitKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome){
+
701  long long int index;
+
702  int bit;
+
703 
+
704  index = blockIdx.x*blockDim.x + threadIdx.x;
+
705  if (index>=stateVecSize) return;
+
706 
+
707  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2);
+
708  bit = extractBit(qubitId, index);
+
709  if (bit==outcome) {
+
710  stateVecReal[index] = normFactor;
+
711  stateVecImag[index] = 0.0;
+
712  } else {
+
713  stateVecReal[index] = 0.0;
+
714  stateVecImag[index] = 0.0;
+
715  }
+
716 }
+
717 
+
718 void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
+
719 {
+
720  int threadsPerCUDABlock, CUDABlocks;
+
721  threadsPerCUDABlock = 128;
+
722  CUDABlocks = ceil((qreal)(qureg->numAmpsPerChunk)/threadsPerCUDABlock);
+
723  statevec_initStateOfSingleQubitKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg->numAmpsPerChunk, qureg->deviceStateVec.real, qureg->deviceStateVec.imag, qubitId, outcome);
+
724 }
+
725 
+
726 // returns 1 if successful, else 0
+
727 int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env){
+
728  long long int chunkSize, stateVecSize;
+
729  long long int indexInChunk, totalIndex;
+
730 
+
731  chunkSize = qureg->numAmpsPerChunk;
+
732  stateVecSize = chunkSize*qureg->numChunks;
+
733 
+
734  qreal *stateVecReal = qureg->stateVec.real;
+
735  qreal *stateVecImag = qureg->stateVec.imag;
+
736 
+
737  FILE *fp;
+
738  char line[200];
+
739 
+
740  fp = fopen(filename, "r");
+
741  if (fp == NULL)
+
742  return 0;
+
743 
+
744  indexInChunk = 0; totalIndex = 0;
+
745  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
+
746  if (line[0]!='#'){
+
747  int chunkId = totalIndex/chunkSize;
+
748  if (chunkId==qureg->chunkId){
+
749  # if QuEST_PREC==1
+
750  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
+
751  &(stateVecImag[indexInChunk]));
+
752  # elif QuEST_PREC==2
+
753  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
754  &(stateVecImag[indexInChunk]));
+
755  # elif QuEST_PREC==4
+
756  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
757  &(stateVecImag[indexInChunk]));
+
758  # endif
+
759  indexInChunk += 1;
+
760  }
+
761  totalIndex += 1;
+
762  }
+
763  }
+
764  fclose(fp);
+
765  copyStateToGPU(*qureg);
+
766 
+
767  // indicate success
+
768  return 1;
+
769 }
+
770 
+
771 int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision){
+
772  qreal diff;
+
773  int chunkSize = mq1.numAmpsPerChunk;
+
774 
+
775  copyStateFromGPU(mq1);
+
776  copyStateFromGPU(mq2);
+
777 
+
778  for (int i=0; i<chunkSize; i++){
+
779  diff = mq1.stateVec.real[i] - mq2.stateVec.real[i];
+
780  if (diff<0) diff *= -1;
+
781  if (diff>precision) return 0;
+
782  diff = mq1.stateVec.imag[i] - mq2.stateVec.imag[i];
+
783  if (diff<0) diff *= -1;
+
784  if (diff>precision) return 0;
+
785  }
+
786  return 1;
+
787 }
+
788 
+
789 __global__ void statevec_compactUnitaryKernel (Qureg qureg, int rotQubit, Complex alpha, Complex beta){
+
790  // ----- sizes
+
791  long long int sizeBlock, // size of blocks
+
792  sizeHalfBlock; // size of blocks halved
+
793  // ----- indices
+
794  long long int thisBlock, // current block
+
795  indexUp,indexLo; // current index and corresponding index in lower half block
+
796 
+
797  // ----- temp variables
+
798  qreal stateRealUp,stateRealLo, // storage for previous state values
+
799  stateImagUp,stateImagLo; // (used in updates)
+
800  // ----- temp variables
+
801  long long int thisTask; // task based approach for expose loop with small granularity
+
802  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
803 
+
804  sizeHalfBlock = 1LL << rotQubit; // size of blocks halved
+
805  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
806 
807  // ---------------------------------------------------------------- //
-
808 
-
810  qreal *stateVecReal = qureg.deviceStateVec.real;
-
811  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
812  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
813  qreal betaImag=beta.imag, betaReal=beta.real;
-
814 
-
815  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
816  if (thisTask>=numTasks) return;
-
817 
-
818  thisBlock = thisTask / sizeHalfBlock;
-
819  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
820  indexLo = indexUp + sizeHalfBlock;
-
821 
-
822  // store current state vector values in temp variables
-
823  stateRealUp = stateVecReal[indexUp];
-
824  stateImagUp = stateVecImag[indexUp];
-
825 
-
826  stateRealLo = stateVecReal[indexLo];
-
827  stateImagLo = stateVecImag[indexLo];
-
828 
-
829  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
830  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
831  - betaReal*stateRealLo - betaImag*stateImagLo;
-
832  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
833  - betaReal*stateImagLo + betaImag*stateRealLo;
-
834 
-
835  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
836  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
837  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
838  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
839  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
840 }
-
841 
-
842 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
-
843 {
-
844  int threadsPerCUDABlock, CUDABlocks;
-
845  threadsPerCUDABlock = 128;
-
846  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
847  statevec_compactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, alpha, beta);
-
848 }
-
849 
-
850 __global__ void statevec_controlledCompactUnitaryKernel (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta){
-
851  // ----- sizes
-
852  long long int sizeBlock, // size of blocks
-
853  sizeHalfBlock; // size of blocks halved
-
854  // ----- indices
-
855  long long int thisBlock, // current block
-
856  indexUp,indexLo; // current index and corresponding index in lower half block
-
857 
-
858  // ----- temp variables
-
859  qreal stateRealUp,stateRealLo, // storage for previous state values
-
860  stateImagUp,stateImagLo; // (used in updates)
-
861  // ----- temp variables
-
862  long long int thisTask; // task based approach for expose loop with small granularity
-
863  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
864  int controlBit;
-
865 
-
866  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
867  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
868 
-
869  // ---------------------------------------------------------------- //
-
870  // rotate //
+
808  // rotate //
+
809  // ---------------------------------------------------------------- //
+
810 
+
812  qreal *stateVecReal = qureg.deviceStateVec.real;
+
813  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
814  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
815  qreal betaImag=beta.imag, betaReal=beta.real;
+
816 
+
817  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
818  if (thisTask>=numTasks) return;
+
819 
+
820  thisBlock = thisTask / sizeHalfBlock;
+
821  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
822  indexLo = indexUp + sizeHalfBlock;
+
823 
+
824  // store current state vector values in temp variables
+
825  stateRealUp = stateVecReal[indexUp];
+
826  stateImagUp = stateVecImag[indexUp];
+
827 
+
828  stateRealLo = stateVecReal[indexLo];
+
829  stateImagLo = stateVecImag[indexLo];
+
830 
+
831  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
832  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
833  - betaReal*stateRealLo - betaImag*stateImagLo;
+
834  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
835  - betaReal*stateImagLo + betaImag*stateRealLo;
+
836 
+
837  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
838  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
839  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
840  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
841  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
842 }
+
843 
+
844 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
845 {
+
846  int threadsPerCUDABlock, CUDABlocks;
+
847  threadsPerCUDABlock = 128;
+
848  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
849  statevec_compactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, alpha, beta);
+
850 }
+
851 
+
852 __global__ void statevec_controlledCompactUnitaryKernel (Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta){
+
853  // ----- sizes
+
854  long long int sizeBlock, // size of blocks
+
855  sizeHalfBlock; // size of blocks halved
+
856  // ----- indices
+
857  long long int thisBlock, // current block
+
858  indexUp,indexLo; // current index and corresponding index in lower half block
+
859 
+
860  // ----- temp variables
+
861  qreal stateRealUp,stateRealLo, // storage for previous state values
+
862  stateImagUp,stateImagLo; // (used in updates)
+
863  // ----- temp variables
+
864  long long int thisTask; // task based approach for expose loop with small granularity
+
865  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
866  int controlBit;
+
867 
+
868  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
869  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
870 
871  // ---------------------------------------------------------------- //
-
872 
-
874  qreal *stateVecReal = qureg.deviceStateVec.real;
-
875  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
876  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
-
877  qreal betaImag=beta.imag, betaReal=beta.real;
-
878 
-
879  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
880  if (thisTask>=numTasks) return;
-
881 
-
882  thisBlock = thisTask / sizeHalfBlock;
-
883  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
884  indexLo = indexUp + sizeHalfBlock;
-
885 
-
886  controlBit = extractBit(controlQubit, indexUp);
-
887  if (controlBit){
-
888  // store current state vector values in temp variables
-
889  stateRealUp = stateVecReal[indexUp];
-
890  stateImagUp = stateVecImag[indexUp];
-
891 
-
892  stateRealLo = stateVecReal[indexLo];
-
893  stateImagLo = stateVecImag[indexLo];
-
894 
-
895  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
-
896  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
-
897  - betaReal*stateRealLo - betaImag*stateImagLo;
-
898  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
-
899  - betaReal*stateImagLo + betaImag*stateRealLo;
-
900 
-
901  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
-
902  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
-
903  + alphaReal*stateRealLo + alphaImag*stateImagLo;
-
904  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
-
905  + alphaReal*stateImagLo - alphaImag*stateRealLo;
-
906  }
-
907 }
-
908 
-
909 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
910 {
-
911  int threadsPerCUDABlock, CUDABlocks;
-
912  threadsPerCUDABlock = 128;
-
913  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
914  statevec_controlledCompactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, alpha, beta);
-
915 }
-
916 
-
917 __global__ void statevec_unitaryKernel(Qureg qureg, int targetQubit, ArgMatrix2 u){
-
918  // ----- sizes
-
919  long long int sizeBlock, // size of blocks
-
920  sizeHalfBlock; // size of blocks halved
-
921  // ----- indices
-
922  long long int thisBlock, // current block
-
923  indexUp,indexLo; // current index and corresponding index in lower half block
-
924 
-
925  // ----- temp variables
-
926  qreal stateRealUp,stateRealLo, // storage for previous state values
-
927  stateImagUp,stateImagLo; // (used in updates)
-
928  // ----- temp variables
-
929  long long int thisTask; // task based approach for expose loop with small granularity
-
930  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
931 
-
932  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
933  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
934 
-
935  // ---------------------------------------------------------------- //
-
936  // rotate //
+
872  // rotate //
+
873  // ---------------------------------------------------------------- //
+
874 
+
876  qreal *stateVecReal = qureg.deviceStateVec.real;
+
877  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
878  qreal alphaImag=alpha.imag, alphaReal=alpha.real;
+
879  qreal betaImag=beta.imag, betaReal=beta.real;
+
880 
+
881  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
882  if (thisTask>=numTasks) return;
+
883 
+
884  thisBlock = thisTask / sizeHalfBlock;
+
885  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
886  indexLo = indexUp + sizeHalfBlock;
+
887 
+
888  controlBit = extractBit(controlQubit, indexUp);
+
889  if (controlBit){
+
890  // store current state vector values in temp variables
+
891  stateRealUp = stateVecReal[indexUp];
+
892  stateImagUp = stateVecImag[indexUp];
+
893 
+
894  stateRealLo = stateVecReal[indexLo];
+
895  stateImagLo = stateVecImag[indexLo];
+
896 
+
897  // state[indexUp] = alpha * state[indexUp] - conj(beta) * state[indexLo]
+
898  stateVecReal[indexUp] = alphaReal*stateRealUp - alphaImag*stateImagUp
+
899  - betaReal*stateRealLo - betaImag*stateImagLo;
+
900  stateVecImag[indexUp] = alphaReal*stateImagUp + alphaImag*stateRealUp
+
901  - betaReal*stateImagLo + betaImag*stateRealLo;
+
902 
+
903  // state[indexLo] = beta * state[indexUp] + conj(alpha) * state[indexLo]
+
904  stateVecReal[indexLo] = betaReal*stateRealUp - betaImag*stateImagUp
+
905  + alphaReal*stateRealLo + alphaImag*stateImagLo;
+
906  stateVecImag[indexLo] = betaReal*stateImagUp + betaImag*stateRealUp
+
907  + alphaReal*stateImagLo - alphaImag*stateRealLo;
+
908  }
+
909 }
+
910 
+
911 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
912 {
+
913  int threadsPerCUDABlock, CUDABlocks;
+
914  threadsPerCUDABlock = 128;
+
915  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
916  statevec_controlledCompactUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, alpha, beta);
+
917 }
+
918 
+
919 __global__ void statevec_unitaryKernel(Qureg qureg, int targetQubit, ArgMatrix2 u){
+
920  // ----- sizes
+
921  long long int sizeBlock, // size of blocks
+
922  sizeHalfBlock; // size of blocks halved
+
923  // ----- indices
+
924  long long int thisBlock, // current block
+
925  indexUp,indexLo; // current index and corresponding index in lower half block
+
926 
+
927  // ----- temp variables
+
928  qreal stateRealUp,stateRealLo, // storage for previous state values
+
929  stateImagUp,stateImagLo; // (used in updates)
+
930  // ----- temp variables
+
931  long long int thisTask; // task based approach for expose loop with small granularity
+
932  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
933 
+
934  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
935  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
936 
937  // ---------------------------------------------------------------- //
-
938 
-
940  qreal *stateVecReal = qureg.deviceStateVec.real;
-
941  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
942 
-
943  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
944  if (thisTask>=numTasks) return;
-
945 
-
946  thisBlock = thisTask / sizeHalfBlock;
-
947  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
948  indexLo = indexUp + sizeHalfBlock;
-
949 
-
950  // store current state vector values in temp variables
-
951  stateRealUp = stateVecReal[indexUp];
-
952  stateImagUp = stateVecImag[indexUp];
-
953 
-
954  stateRealLo = stateVecReal[indexLo];
-
955  stateImagLo = stateVecImag[indexLo];
-
956 
-
957  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
958  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
959  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
960  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
961  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
962 
-
963  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
964  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
965  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
966  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
967  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
968 }
-
969 
-
970 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
971 {
-
972  int threadsPerCUDABlock, CUDABlocks;
-
973  threadsPerCUDABlock = 128;
-
974  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
975  statevec_unitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, argifyMatrix2(u));
-
976 }
-
977 
- -
979  Qureg qureg, long long int ctrlMask, int* targs, int numTargs,
-
980  qreal* uRe, qreal* uIm, long long int* ampInds, qreal* reAmps, qreal* imAmps, long long int numTargAmps)
-
981 {
-
982 
-
983  // decide the amplitudes this thread will modify
-
984  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
985  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
-
986  if (thisTask>=numTasks) return;
-
987 
-
988  // find this task's start index (where all targs are 0)
-
989  long long int ind00 = insertZeroBits(thisTask, targs, numTargs);
-
990 
-
991  // this task only modifies amplitudes if control qubits are 1 for this state
-
992  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
993  return;
-
994 
-
995  qreal *reVec = qureg.deviceStateVec.real;
-
996  qreal *imVec = qureg.deviceStateVec.imag;
-
997 
-
998  /*
-
999  each thread needs:
-
1000  long long int ampInds[numAmps];
-
1001  qreal reAmps[numAmps];
-
1002  qreal imAmps[numAmps];
-
1003  but instead has access to shared arrays, with below stride and offset
-
1004  */
-
1005  size_t stride = gridDim.x*blockDim.x;
-
1006  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
1007 
-
1008  // determine the indices and record values of target amps
-
1009  long long int ind;
-
1010  for (int i=0; i < numTargAmps; i++) {
-
1011 
-
1012  // get global index of current target qubit assignment
-
1013  ind = ind00;
-
1014  for (int t=0; t < numTargs; t++)
-
1015  if (extractBit(t, i))
-
1016  ind = flipBit(ind, targs[t]);
-
1017 
-
1018  ampInds[i*stride+offset] = ind;
-
1019  reAmps [i*stride+offset] = reVec[ind];
-
1020  imAmps [i*stride+offset] = imVec[ind];
-
1021  }
-
1022 
-
1023  // update the amplitudes
-
1024  for (int r=0; r < numTargAmps; r++) {
-
1025  ind = ampInds[r*stride+offset];
-
1026  reVec[ind] = 0;
-
1027  imVec[ind] = 0;
-
1028  for (int c=0; c < numTargAmps; c++) {
-
1029  qreal uReElem = uRe[c + r*numTargAmps];
-
1030  qreal uImElem = uIm[c + r*numTargAmps];
-
1031  reVec[ind] += reAmps[c*stride+offset]*uReElem - imAmps[c*stride+offset]*uImElem;
-
1032  imVec[ind] += reAmps[c*stride+offset]*uImElem + imAmps[c*stride+offset]*uReElem;
-
1033  }
-
1034  }
-
1035 }
-
1036 
-
1037 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
-
1038 {
-
1039  int threadsPerCUDABlock = 128;
-
1040  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>numTargs)/threadsPerCUDABlock);
-
1041 
-
1042  // allocate device space for global {targs} (length: numTargs) and populate
-
1043  int *d_targs;
-
1044  size_t targMemSize = numTargs * sizeof *d_targs;
-
1045  cudaMalloc(&d_targs, targMemSize);
-
1046  cudaMemcpy(d_targs, targs, targMemSize, cudaMemcpyHostToDevice);
-
1047 
-
1048  // flatten out the u.real and u.imag lists
-
1049  int uNumRows = (1 << u.numQubits);
-
1050  qreal* uReFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uReFlat);
-
1051  qreal* uImFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uImFlat);
-
1052  long long int i = 0;
-
1053  for (int r=0; r < uNumRows; r++)
-
1054  for (int c=0; c < uNumRows; c++) {
-
1055  uReFlat[i] = u.real[r][c];
-
1056  uImFlat[i] = u.imag[r][c];
-
1057  i++;
-
1058  }
-
1059 
-
1060  // allocate device space for global u.real and u.imag (flatten by concatenating rows) and populate
-
1061  qreal* d_uRe;
-
1062  qreal* d_uIm;
-
1063  size_t uMemSize = uNumRows*uNumRows * sizeof *d_uRe; // size of each of d_uRe and d_uIm
-
1064  cudaMalloc(&d_uRe, uMemSize);
-
1065  cudaMalloc(&d_uIm, uMemSize);
-
1066  cudaMemcpy(d_uRe, uReFlat, uMemSize, cudaMemcpyHostToDevice);
-
1067  cudaMemcpy(d_uIm, uImFlat, uMemSize, cudaMemcpyHostToDevice);
-
1068 
-
1069  // allocate device Wspace for thread-local {ampInds}, {reAmps}, {imAmps} (length: 1<<numTargs)
-
1070  long long int *d_ampInds;
-
1071  qreal *d_reAmps;
-
1072  qreal *d_imAmps;
-
1073  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
1074  int numTargAmps = uNumRows;
-
1075  cudaMalloc(&d_ampInds, numTargAmps*gridSize * sizeof *d_ampInds);
-
1076  cudaMalloc(&d_reAmps, numTargAmps*gridSize * sizeof *d_reAmps);
-
1077  cudaMalloc(&d_imAmps, numTargAmps*gridSize * sizeof *d_imAmps);
-
1078 
-
1079  // call kernel
-
1080  statevec_multiControlledMultiQubitUnitaryKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
1081  qureg, ctrlMask, d_targs, numTargs, d_uRe, d_uIm, d_ampInds, d_reAmps, d_imAmps, numTargAmps);
-
1082 
-
1083  // free kernel memory
-
1084  free(uReFlat);
-
1085  free(uImFlat);
-
1086  cudaFree(d_targs);
-
1087  cudaFree(d_uRe);
-
1088  cudaFree(d_uIm);
-
1089  cudaFree(d_ampInds);
-
1090  cudaFree(d_reAmps);
-
1091  cudaFree(d_imAmps);
-
1092 }
-
1093 
-
1094 __global__ void statevec_multiControlledTwoQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u){
-
1095 
-
1096  // decide the 4 amplitudes this thread will modify
-
1097  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1098  long long int numTasks = qureg.numAmpsPerChunk >> 2; // kernel called on every 1 in 4 amplitudes
-
1099  if (thisTask>=numTasks) return;
-
1100 
-
1101  qreal *reVec = qureg.deviceStateVec.real;
-
1102  qreal *imVec = qureg.deviceStateVec.imag;
-
1103 
-
1104  // find indices of amplitudes to modify (treat q1 as the least significant bit)
-
1105  long long int ind00, ind01, ind10, ind11;
-
1106  ind00 = insertTwoZeroBits(thisTask, q1, q2);
-
1107 
-
1108  // modify only if control qubits are 1 for this state
-
1109  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
-
1110  return;
-
1111 
-
1112  ind01 = flipBit(ind00, q1);
-
1113  ind10 = flipBit(ind00, q2);
-
1114  ind11 = flipBit(ind01, q2);
-
1115 
-
1116  // extract statevec amplitudes
-
1117  qreal re00, re01, re10, re11;
-
1118  qreal im00, im01, im10, im11;
-
1119  re00 = reVec[ind00]; im00 = imVec[ind00];
-
1120  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1121  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1122  re11 = reVec[ind11]; im11 = imVec[ind11];
-
1123 
-
1124  // apply u * {amp00, amp01, amp10, amp11}
-
1125  reVec[ind00] =
-
1126  u.r0c0.real*re00 - u.r0c0.imag*im00 +
-
1127  u.r0c1.real*re01 - u.r0c1.imag*im01 +
-
1128  u.r0c2.real*re10 - u.r0c2.imag*im10 +
-
1129  u.r0c3.real*re11 - u.r0c3.imag*im11;
-
1130  imVec[ind00] =
-
1131  u.r0c0.imag*re00 + u.r0c0.real*im00 +
-
1132  u.r0c1.imag*re01 + u.r0c1.real*im01 +
-
1133  u.r0c2.imag*re10 + u.r0c2.real*im10 +
-
1134  u.r0c3.imag*re11 + u.r0c3.real*im11;
-
1135 
-
1136  reVec[ind01] =
-
1137  u.r1c0.real*re00 - u.r1c0.imag*im00 +
-
1138  u.r1c1.real*re01 - u.r1c1.imag*im01 +
-
1139  u.r1c2.real*re10 - u.r1c2.imag*im10 +
-
1140  u.r1c3.real*re11 - u.r1c3.imag*im11;
-
1141  imVec[ind01] =
-
1142  u.r1c0.imag*re00 + u.r1c0.real*im00 +
-
1143  u.r1c1.imag*re01 + u.r1c1.real*im01 +
-
1144  u.r1c2.imag*re10 + u.r1c2.real*im10 +
-
1145  u.r1c3.imag*re11 + u.r1c3.real*im11;
-
1146 
-
1147  reVec[ind10] =
-
1148  u.r2c0.real*re00 - u.r2c0.imag*im00 +
-
1149  u.r2c1.real*re01 - u.r2c1.imag*im01 +
-
1150  u.r2c2.real*re10 - u.r2c2.imag*im10 +
-
1151  u.r2c3.real*re11 - u.r2c3.imag*im11;
-
1152  imVec[ind10] =
-
1153  u.r2c0.imag*re00 + u.r2c0.real*im00 +
-
1154  u.r2c1.imag*re01 + u.r2c1.real*im01 +
-
1155  u.r2c2.imag*re10 + u.r2c2.real*im10 +
-
1156  u.r2c3.imag*re11 + u.r2c3.real*im11;
-
1157 
-
1158  reVec[ind11] =
-
1159  u.r3c0.real*re00 - u.r3c0.imag*im00 +
-
1160  u.r3c1.real*re01 - u.r3c1.imag*im01 +
-
1161  u.r3c2.real*re10 - u.r3c2.imag*im10 +
-
1162  u.r3c3.real*re11 - u.r3c3.imag*im11;
-
1163  imVec[ind11] =
-
1164  u.r3c0.imag*re00 + u.r3c0.real*im00 +
-
1165  u.r3c1.imag*re01 + u.r3c1.real*im01 +
-
1166  u.r3c2.imag*re10 + u.r3c2.real*im10 +
-
1167  u.r3c3.imag*re11 + u.r3c3.real*im11;
-
1168 }
-
1169 
-
1170 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
-
1171 {
-
1172  int threadsPerCUDABlock = 128;
-
1173  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock); // one kernel eval for every 4 amplitudes
-
1174  statevec_multiControlledTwoQubitUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, q1, q2, argifyMatrix4(u));
-
1175 }
-
1176 
-
1177 __global__ void statevec_controlledUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u){
-
1178  // ----- sizes
-
1179  long long int sizeBlock, // size of blocks
-
1180  sizeHalfBlock; // size of blocks halved
-
1181  // ----- indices
-
1182  long long int thisBlock, // current block
-
1183  indexUp,indexLo; // current index and corresponding index in lower half block
-
1184 
-
1185  // ----- temp variables
-
1186  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1187  stateImagUp,stateImagLo; // (used in updates)
-
1188  // ----- temp variables
-
1189  long long int thisTask; // task based approach for expose loop with small granularity
-
1190  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1191 
-
1192  int controlBit;
+
938  // rotate //
+
939  // ---------------------------------------------------------------- //
+
940 
+
942  qreal *stateVecReal = qureg.deviceStateVec.real;
+
943  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
944 
+
945  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
946  if (thisTask>=numTasks) return;
+
947 
+
948  thisBlock = thisTask / sizeHalfBlock;
+
949  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
950  indexLo = indexUp + sizeHalfBlock;
+
951 
+
952  // store current state vector values in temp variables
+
953  stateRealUp = stateVecReal[indexUp];
+
954  stateImagUp = stateVecImag[indexUp];
+
955 
+
956  stateRealLo = stateVecReal[indexLo];
+
957  stateImagLo = stateVecImag[indexLo];
+
958 
+
959  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
960  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
+
961  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
+
962  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
+
963  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
+
964 
+
965  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
966  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
+
967  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
+
968  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
+
969  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
+
970 }
+
971 
+
972 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
973 {
+
974  int threadsPerCUDABlock, CUDABlocks;
+
975  threadsPerCUDABlock = 128;
+
976  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
977  statevec_unitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, argifyMatrix2(u));
+
978 }
+
979 
+ +
981  Qureg qureg, long long int ctrlMask, int* targs, int numTargs,
+
982  qreal* uRe, qreal* uIm, long long int* ampInds, qreal* reAmps, qreal* imAmps, long long int numTargAmps)
+
983 {
+
984 
+
985  // decide the amplitudes this thread will modify
+
986  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
987  long long int numTasks = qureg.numAmpsPerChunk >> numTargs; // kernel called on every 1 in 2^numTargs amplitudes
+
988  if (thisTask>=numTasks) return;
+
989 
+
990  // find this task's start index (where all targs are 0)
+
991  long long int ind00 = insertZeroBits(thisTask, targs, numTargs);
+
992 
+
993  // this task only modifies amplitudes if control qubits are 1 for this state
+
994  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
+
995  return;
+
996 
+
997  qreal *reVec = qureg.deviceStateVec.real;
+
998  qreal *imVec = qureg.deviceStateVec.imag;
+
999 
+
1000  /*
+
1001  each thread needs:
+
1002  long long int ampInds[numAmps];
+
1003  qreal reAmps[numAmps];
+
1004  qreal imAmps[numAmps];
+
1005  but instead has access to shared arrays, with below stride and offset
+
1006  */
+
1007  size_t stride = gridDim.x*blockDim.x;
+
1008  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
+
1009 
+
1010  // determine the indices and record values of target amps
+
1011  long long int ind;
+
1012  for (int i=0; i < numTargAmps; i++) {
+
1013 
+
1014  // get global index of current target qubit assignment
+
1015  ind = ind00;
+
1016  for (int t=0; t < numTargs; t++)
+
1017  if (extractBit(t, i))
+
1018  ind = flipBit(ind, targs[t]);
+
1019 
+
1020  ampInds[i*stride+offset] = ind;
+
1021  reAmps [i*stride+offset] = reVec[ind];
+
1022  imAmps [i*stride+offset] = imVec[ind];
+
1023  }
+
1024 
+
1025  // update the amplitudes
+
1026  for (int r=0; r < numTargAmps; r++) {
+
1027  ind = ampInds[r*stride+offset];
+
1028  reVec[ind] = 0;
+
1029  imVec[ind] = 0;
+
1030  for (int c=0; c < numTargAmps; c++) {
+
1031  qreal uReElem = uRe[c + r*numTargAmps];
+
1032  qreal uImElem = uIm[c + r*numTargAmps];
+
1033  reVec[ind] += reAmps[c*stride+offset]*uReElem - imAmps[c*stride+offset]*uImElem;
+
1034  imVec[ind] += reAmps[c*stride+offset]*uImElem + imAmps[c*stride+offset]*uReElem;
+
1035  }
+
1036  }
+
1037 }
+
1038 
+
1039 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
+
1040 {
+
1041  int threadsPerCUDABlock = 128;
+
1042  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>numTargs)/threadsPerCUDABlock);
+
1043 
+
1044  // allocate device space for global {targs} (length: numTargs) and populate
+
1045  int *d_targs;
+
1046  size_t targMemSize = numTargs * sizeof *d_targs;
+
1047  cudaMalloc(&d_targs, targMemSize);
+
1048  cudaMemcpy(d_targs, targs, targMemSize, cudaMemcpyHostToDevice);
+
1049 
+
1050  // flatten out the u.real and u.imag lists
+
1051  int uNumRows = (1 << u.numQubits);
+
1052  qreal* uReFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uReFlat);
+
1053  qreal* uImFlat = (qreal*) malloc(uNumRows*uNumRows * sizeof *uImFlat);
+
1054  long long int i = 0;
+
1055  for (int r=0; r < uNumRows; r++)
+
1056  for (int c=0; c < uNumRows; c++) {
+
1057  uReFlat[i] = u.real[r][c];
+
1058  uImFlat[i] = u.imag[r][c];
+
1059  i++;
+
1060  }
+
1061 
+
1062  // allocate device space for global u.real and u.imag (flatten by concatenating rows) and populate
+
1063  qreal* d_uRe;
+
1064  qreal* d_uIm;
+
1065  size_t uMemSize = uNumRows*uNumRows * sizeof *d_uRe; // size of each of d_uRe and d_uIm
+
1066  cudaMalloc(&d_uRe, uMemSize);
+
1067  cudaMalloc(&d_uIm, uMemSize);
+
1068  cudaMemcpy(d_uRe, uReFlat, uMemSize, cudaMemcpyHostToDevice);
+
1069  cudaMemcpy(d_uIm, uImFlat, uMemSize, cudaMemcpyHostToDevice);
+
1070 
+
1071  // allocate device Wspace for thread-local {ampInds}, {reAmps}, {imAmps} (length: 1<<numTargs)
+
1072  long long int *d_ampInds;
+
1073  qreal *d_reAmps;
+
1074  qreal *d_imAmps;
+
1075  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
+
1076  int numTargAmps = uNumRows;
+
1077  cudaMalloc(&d_ampInds, numTargAmps*gridSize * sizeof *d_ampInds);
+
1078  cudaMalloc(&d_reAmps, numTargAmps*gridSize * sizeof *d_reAmps);
+
1079  cudaMalloc(&d_imAmps, numTargAmps*gridSize * sizeof *d_imAmps);
+
1080 
+
1081  // call kernel
+
1082  statevec_multiControlledMultiQubitUnitaryKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
1083  qureg, ctrlMask, d_targs, numTargs, d_uRe, d_uIm, d_ampInds, d_reAmps, d_imAmps, numTargAmps);
+
1084 
+
1085  // free kernel memory
+
1086  free(uReFlat);
+
1087  free(uImFlat);
+
1088  cudaFree(d_targs);
+
1089  cudaFree(d_uRe);
+
1090  cudaFree(d_uIm);
+
1091  cudaFree(d_ampInds);
+
1092  cudaFree(d_reAmps);
+
1093  cudaFree(d_imAmps);
+
1094 }
+
1095 
+
1096 __global__ void statevec_multiControlledTwoQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u){
+
1097 
+
1098  // decide the 4 amplitudes this thread will modify
+
1099  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1100  long long int numTasks = qureg.numAmpsPerChunk >> 2; // kernel called on every 1 in 4 amplitudes
+
1101  if (thisTask>=numTasks) return;
+
1102 
+
1103  qreal *reVec = qureg.deviceStateVec.real;
+
1104  qreal *imVec = qureg.deviceStateVec.imag;
+
1105 
+
1106  // find indices of amplitudes to modify (treat q1 as the least significant bit)
+
1107  long long int ind00, ind01, ind10, ind11;
+
1108  ind00 = insertTwoZeroBits(thisTask, q1, q2);
+
1109 
+
1110  // modify only if control qubits are 1 for this state
+
1111  if (ctrlMask && (ctrlMask&ind00) != ctrlMask)
+
1112  return;
+
1113 
+
1114  ind01 = flipBit(ind00, q1);
+
1115  ind10 = flipBit(ind00, q2);
+
1116  ind11 = flipBit(ind01, q2);
+
1117 
+
1118  // extract statevec amplitudes
+
1119  qreal re00, re01, re10, re11;
+
1120  qreal im00, im01, im10, im11;
+
1121  re00 = reVec[ind00]; im00 = imVec[ind00];
+
1122  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1123  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1124  re11 = reVec[ind11]; im11 = imVec[ind11];
+
1125 
+
1126  // apply u * {amp00, amp01, amp10, amp11}
+
1127  reVec[ind00] =
+
1128  u.r0c0.real*re00 - u.r0c0.imag*im00 +
+
1129  u.r0c1.real*re01 - u.r0c1.imag*im01 +
+
1130  u.r0c2.real*re10 - u.r0c2.imag*im10 +
+
1131  u.r0c3.real*re11 - u.r0c3.imag*im11;
+
1132  imVec[ind00] =
+
1133  u.r0c0.imag*re00 + u.r0c0.real*im00 +
+
1134  u.r0c1.imag*re01 + u.r0c1.real*im01 +
+
1135  u.r0c2.imag*re10 + u.r0c2.real*im10 +
+
1136  u.r0c3.imag*re11 + u.r0c3.real*im11;
+
1137 
+
1138  reVec[ind01] =
+
1139  u.r1c0.real*re00 - u.r1c0.imag*im00 +
+
1140  u.r1c1.real*re01 - u.r1c1.imag*im01 +
+
1141  u.r1c2.real*re10 - u.r1c2.imag*im10 +
+
1142  u.r1c3.real*re11 - u.r1c3.imag*im11;
+
1143  imVec[ind01] =
+
1144  u.r1c0.imag*re00 + u.r1c0.real*im00 +
+
1145  u.r1c1.imag*re01 + u.r1c1.real*im01 +
+
1146  u.r1c2.imag*re10 + u.r1c2.real*im10 +
+
1147  u.r1c3.imag*re11 + u.r1c3.real*im11;
+
1148 
+
1149  reVec[ind10] =
+
1150  u.r2c0.real*re00 - u.r2c0.imag*im00 +
+
1151  u.r2c1.real*re01 - u.r2c1.imag*im01 +
+
1152  u.r2c2.real*re10 - u.r2c2.imag*im10 +
+
1153  u.r2c3.real*re11 - u.r2c3.imag*im11;
+
1154  imVec[ind10] =
+
1155  u.r2c0.imag*re00 + u.r2c0.real*im00 +
+
1156  u.r2c1.imag*re01 + u.r2c1.real*im01 +
+
1157  u.r2c2.imag*re10 + u.r2c2.real*im10 +
+
1158  u.r2c3.imag*re11 + u.r2c3.real*im11;
+
1159 
+
1160  reVec[ind11] =
+
1161  u.r3c0.real*re00 - u.r3c0.imag*im00 +
+
1162  u.r3c1.real*re01 - u.r3c1.imag*im01 +
+
1163  u.r3c2.real*re10 - u.r3c2.imag*im10 +
+
1164  u.r3c3.real*re11 - u.r3c3.imag*im11;
+
1165  imVec[ind11] =
+
1166  u.r3c0.imag*re00 + u.r3c0.real*im00 +
+
1167  u.r3c1.imag*re01 + u.r3c1.real*im01 +
+
1168  u.r3c2.imag*re10 + u.r3c2.real*im10 +
+
1169  u.r3c3.imag*re11 + u.r3c3.real*im11;
+
1170 }
+
1171 
+
1172 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
+
1173 {
+
1174  int threadsPerCUDABlock = 128;
+
1175  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock); // one kernel eval for every 4 amplitudes
+
1176  statevec_multiControlledTwoQubitUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, q1, q2, argifyMatrix4(u));
+
1177 }
+
1178 
+
1179 __global__ void statevec_controlledUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u){
+
1180  // ----- sizes
+
1181  long long int sizeBlock, // size of blocks
+
1182  sizeHalfBlock; // size of blocks halved
+
1183  // ----- indices
+
1184  long long int thisBlock, // current block
+
1185  indexUp,indexLo; // current index and corresponding index in lower half block
+
1186 
+
1187  // ----- temp variables
+
1188  qreal stateRealUp,stateRealLo, // storage for previous state values
+
1189  stateImagUp,stateImagLo; // (used in updates)
+
1190  // ----- temp variables
+
1191  long long int thisTask; // task based approach for expose loop with small granularity
+
1192  long long int numTasks=qureg.numAmpsPerChunk>>1;
1193 
-
1194  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1195  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1196 
-
1197  // ---------------------------------------------------------------- //
-
1198  // rotate //
+
1194  int controlBit;
+
1195 
+
1196  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1197  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1198 
1199  // ---------------------------------------------------------------- //
-
1200 
-
1202  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1203  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1204 
-
1205  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1206  if (thisTask>=numTasks) return;
-
1207 
-
1208  thisBlock = thisTask / sizeHalfBlock;
-
1209  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1210  indexLo = indexUp + sizeHalfBlock;
-
1211 
-
1212  // store current state vector values in temp variables
-
1213  stateRealUp = stateVecReal[indexUp];
-
1214  stateImagUp = stateVecImag[indexUp];
-
1215 
-
1216  stateRealLo = stateVecReal[indexLo];
-
1217  stateImagLo = stateVecImag[indexLo];
-
1218 
-
1219  controlBit = extractBit(controlQubit, indexUp);
-
1220  if (controlBit){
-
1221  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1222  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1223  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1224  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1225  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1226 
-
1227  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1228  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1229  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1230  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1231  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1232  }
-
1233 }
-
1234 
-
1235 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
1236 {
-
1237  int threadsPerCUDABlock, CUDABlocks;
-
1238  threadsPerCUDABlock = 128;
-
1239  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1240  statevec_controlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, argifyMatrix2(u));
-
1241 }
-
1242 
- -
1244  Qureg qureg,
-
1245  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
1246  int targetQubit, ArgMatrix2 u
-
1247 ){
-
1248  // ----- sizes
-
1249  long long int sizeBlock, // size of blocks
-
1250  sizeHalfBlock; // size of blocks halved
-
1251  // ----- indices
-
1252  long long int thisBlock, // current block
-
1253  indexUp,indexLo; // current index and corresponding index in lower half block
-
1254 
-
1255  // ----- temp variables
-
1256  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1257  stateImagUp,stateImagLo; // (used in updates)
-
1258  // ----- temp variables
-
1259  long long int thisTask; // task based approach for expose loop with small granularity
-
1260  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1261 
-
1262 
-
1263  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1264  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1265 
-
1266  // ---------------------------------------------------------------- //
-
1267  // rotate //
+
1200  // rotate //
+
1201  // ---------------------------------------------------------------- //
+
1202 
+
1204  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1205  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1206 
+
1207  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1208  if (thisTask>=numTasks) return;
+
1209 
+
1210  thisBlock = thisTask / sizeHalfBlock;
+
1211  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1212  indexLo = indexUp + sizeHalfBlock;
+
1213 
+
1214  // store current state vector values in temp variables
+
1215  stateRealUp = stateVecReal[indexUp];
+
1216  stateImagUp = stateVecImag[indexUp];
+
1217 
+
1218  stateRealLo = stateVecReal[indexLo];
+
1219  stateImagLo = stateVecImag[indexLo];
+
1220 
+
1221  controlBit = extractBit(controlQubit, indexUp);
+
1222  if (controlBit){
+
1223  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
1224  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
+
1225  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
+
1226  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
+
1227  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
+
1228 
+
1229  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
1230  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
+
1231  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
+
1232  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
+
1233  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
+
1234  }
+
1235 }
+
1236 
+
1237 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
+
1238 {
+
1239  int threadsPerCUDABlock, CUDABlocks;
+
1240  threadsPerCUDABlock = 128;
+
1241  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1242  statevec_controlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, argifyMatrix2(u));
+
1243 }
+
1244 
+ +
1246  Qureg qureg,
+
1247  long long int ctrlQubitsMask, long long int ctrlFlipMask,
+
1248  int targetQubit, ArgMatrix2 u
+
1249 ){
+
1250  // ----- sizes
+
1251  long long int sizeBlock, // size of blocks
+
1252  sizeHalfBlock; // size of blocks halved
+
1253  // ----- indices
+
1254  long long int thisBlock, // current block
+
1255  indexUp,indexLo; // current index and corresponding index in lower half block
+
1256 
+
1257  // ----- temp variables
+
1258  qreal stateRealUp,stateRealLo, // storage for previous state values
+
1259  stateImagUp,stateImagLo; // (used in updates)
+
1260  // ----- temp variables
+
1261  long long int thisTask; // task based approach for expose loop with small granularity
+
1262  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1263 
+
1264 
+
1265  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1266  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1267 
1268  // ---------------------------------------------------------------- //
-
1269 
-
1271  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1272  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1273 
-
1274  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1275  if (thisTask>=numTasks) return;
-
1276 
-
1277  thisBlock = thisTask / sizeHalfBlock;
-
1278  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1279  indexLo = indexUp + sizeHalfBlock;
-
1280 
-
1281  if (ctrlQubitsMask == (ctrlQubitsMask & (indexUp ^ ctrlFlipMask))) {
-
1282  // store current state vector values in temp variables
-
1283  stateRealUp = stateVecReal[indexUp];
-
1284  stateImagUp = stateVecImag[indexUp];
-
1285 
-
1286  stateRealLo = stateVecReal[indexLo];
-
1287  stateImagLo = stateVecImag[indexLo];
-
1288 
-
1289  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
-
1290  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
-
1291  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
-
1292  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
-
1293  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
-
1294 
-
1295  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
-
1296  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
-
1297  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
-
1298  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
-
1299  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
-
1300  }
-
1301 }
-
1302 
- -
1304  Qureg qureg,
-
1305  long long int ctrlQubitsMask, long long int ctrlFlipMask,
-
1306  int targetQubit, ComplexMatrix2 u
-
1307 ){
-
1308  int threadsPerCUDABlock = 128;
-
1309  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1310  statevec_multiControlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
1311  qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, argifyMatrix2(u));
-
1312 }
-
1313 
-
1314 __global__ void statevec_pauliXKernel(Qureg qureg, int targetQubit){
-
1315  // ----- sizes
-
1316  long long int sizeBlock, // size of blocks
-
1317  sizeHalfBlock; // size of blocks halved
-
1318  // ----- indices
-
1319  long long int thisBlock, // current block
-
1320  indexUp,indexLo; // current index and corresponding index in lower half block
-
1321 
-
1322  // ----- temp variables
-
1323  qreal stateRealUp, // storage for previous state values
-
1324  stateImagUp; // (used in updates)
-
1325  // ----- temp variables
-
1326  long long int thisTask; // task based approach for expose loop with small granularity
-
1327  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1328 
-
1329  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1330  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1331 
-
1332  // ---------------------------------------------------------------- //
-
1333  // rotate //
+
1269  // rotate //
+
1270  // ---------------------------------------------------------------- //
+
1271 
+
1273  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1274  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1275 
+
1276  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1277  if (thisTask>=numTasks) return;
+
1278 
+
1279  thisBlock = thisTask / sizeHalfBlock;
+
1280  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1281  indexLo = indexUp + sizeHalfBlock;
+
1282 
+
1283  if (ctrlQubitsMask == (ctrlQubitsMask & (indexUp ^ ctrlFlipMask))) {
+
1284  // store current state vector values in temp variables
+
1285  stateRealUp = stateVecReal[indexUp];
+
1286  stateImagUp = stateVecImag[indexUp];
+
1287 
+
1288  stateRealLo = stateVecReal[indexLo];
+
1289  stateImagLo = stateVecImag[indexLo];
+
1290 
+
1291  // state[indexUp] = u00 * state[indexUp] + u01 * state[indexLo]
+
1292  stateVecReal[indexUp] = u.r0c0.real*stateRealUp - u.r0c0.imag*stateImagUp
+
1293  + u.r0c1.real*stateRealLo - u.r0c1.imag*stateImagLo;
+
1294  stateVecImag[indexUp] = u.r0c0.real*stateImagUp + u.r0c0.imag*stateRealUp
+
1295  + u.r0c1.real*stateImagLo + u.r0c1.imag*stateRealLo;
+
1296 
+
1297  // state[indexLo] = u10 * state[indexUp] + u11 * state[indexLo]
+
1298  stateVecReal[indexLo] = u.r1c0.real*stateRealUp - u.r1c0.imag*stateImagUp
+
1299  + u.r1c1.real*stateRealLo - u.r1c1.imag*stateImagLo;
+
1300  stateVecImag[indexLo] = u.r1c0.real*stateImagUp + u.r1c0.imag*stateRealUp
+
1301  + u.r1c1.real*stateImagLo + u.r1c1.imag*stateRealLo;
+
1302  }
+
1303 }
+
1304 
+ +
1306  Qureg qureg,
+
1307  long long int ctrlQubitsMask, long long int ctrlFlipMask,
+
1308  int targetQubit, ComplexMatrix2 u
+
1309 ){
+
1310  int threadsPerCUDABlock = 128;
+
1311  int CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1312  statevec_multiControlledUnitaryKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
1313  qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, argifyMatrix2(u));
+
1314 }
+
1315 
+
1316 __global__ void statevec_pauliXKernel(Qureg qureg, int targetQubit){
+
1317  // ----- sizes
+
1318  long long int sizeBlock, // size of blocks
+
1319  sizeHalfBlock; // size of blocks halved
+
1320  // ----- indices
+
1321  long long int thisBlock, // current block
+
1322  indexUp,indexLo; // current index and corresponding index in lower half block
+
1323 
+
1324  // ----- temp variables
+
1325  qreal stateRealUp, // storage for previous state values
+
1326  stateImagUp; // (used in updates)
+
1327  // ----- temp variables
+
1328  long long int thisTask; // task based approach for expose loop with small granularity
+
1329  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1330 
+
1331  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1332  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1333 
1334  // ---------------------------------------------------------------- //
-
1335 
-
1337  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1338  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1339 
-
1340  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1341  if (thisTask>=numTasks) return;
-
1342 
-
1343  thisBlock = thisTask / sizeHalfBlock;
-
1344  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1345  indexLo = indexUp + sizeHalfBlock;
-
1346 
-
1347  // store current state vector values in temp variables
-
1348  stateRealUp = stateVecReal[indexUp];
-
1349  stateImagUp = stateVecImag[indexUp];
-
1350 
-
1351  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1352  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1353 
-
1354  stateVecReal[indexLo] = stateRealUp;
-
1355  stateVecImag[indexLo] = stateImagUp;
-
1356 }
-
1357 
-
1358 void statevec_pauliX(Qureg qureg, int targetQubit)
-
1359 {
-
1360  int threadsPerCUDABlock, CUDABlocks;
-
1361  threadsPerCUDABlock = 128;
-
1362  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1363  statevec_pauliXKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1364 }
-
1365 
-
1366 __global__ void statevec_pauliYKernel(Qureg qureg, int targetQubit, int conjFac){
+
1335  // rotate //
+
1336  // ---------------------------------------------------------------- //
+
1337 
+
1339  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1340  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1341 
+
1342  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1343  if (thisTask>=numTasks) return;
+
1344 
+
1345  thisBlock = thisTask / sizeHalfBlock;
+
1346  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1347  indexLo = indexUp + sizeHalfBlock;
+
1348 
+
1349  // store current state vector values in temp variables
+
1350  stateRealUp = stateVecReal[indexUp];
+
1351  stateImagUp = stateVecImag[indexUp];
+
1352 
+
1353  stateVecReal[indexUp] = stateVecReal[indexLo];
+
1354  stateVecImag[indexUp] = stateVecImag[indexLo];
+
1355 
+
1356  stateVecReal[indexLo] = stateRealUp;
+
1357  stateVecImag[indexLo] = stateImagUp;
+
1358 }
+
1359 
+
1360 void statevec_pauliX(Qureg qureg, int targetQubit)
+
1361 {
+
1362  int threadsPerCUDABlock, CUDABlocks;
+
1363  threadsPerCUDABlock = 128;
+
1364  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1365  statevec_pauliXKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
+
1366 }
1367 
-
1368  long long int sizeHalfBlock = 1LL << targetQubit;
-
1369  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1370  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1371  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1372  if (thisTask>=numTasks) return;
-
1373 
-
1374  long long int thisBlock = thisTask / sizeHalfBlock;
-
1375  long long int indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1376  long long int indexLo = indexUp + sizeHalfBlock;
-
1377  qreal stateRealUp, stateImagUp;
-
1378 
-
1379  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1380  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1381  stateRealUp = stateVecReal[indexUp];
-
1382  stateImagUp = stateVecImag[indexUp];
-
1383 
-
1384  // update under +-{{0, -i}, {i, 0}}
-
1385  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1386  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1387  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1388  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1389 }
-
1390 
-
1391 void statevec_pauliY(Qureg qureg, int targetQubit)
-
1392 {
-
1393  int threadsPerCUDABlock, CUDABlocks;
-
1394  threadsPerCUDABlock = 128;
-
1395  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1396  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, 1);
-
1397 }
-
1398 
-
1399 void statevec_pauliYConj(Qureg qureg, int targetQubit)
-
1400 {
-
1401  int threadsPerCUDABlock, CUDABlocks;
-
1402  threadsPerCUDABlock = 128;
-
1403  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1404  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, -1);
-
1405 }
-
1406 
-
1407 __global__ void statevec_controlledPauliYKernel(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
-
1408 {
-
1409  long long int index;
-
1410  long long int sizeBlock, sizeHalfBlock;
-
1411  long long int stateVecSize;
-
1412  int controlBit;
-
1413 
-
1414  qreal stateRealUp, stateImagUp;
-
1415  long long int thisBlock, indexUp, indexLo;
-
1416  sizeHalfBlock = 1LL << targetQubit;
-
1417  sizeBlock = 2LL * sizeHalfBlock;
-
1418 
-
1419  stateVecSize = qureg.numAmpsPerChunk;
-
1420  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1421  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1422 
-
1423  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1424  if (index>=(stateVecSize>>1)) return;
-
1425  thisBlock = index / sizeHalfBlock;
-
1426  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1427  indexLo = indexUp + sizeHalfBlock;
-
1428 
-
1429  controlBit = extractBit(controlQubit, indexUp);
-
1430  if (controlBit){
-
1431 
-
1432  stateRealUp = stateVecReal[indexUp];
-
1433  stateImagUp = stateVecImag[indexUp];
-
1434 
-
1435  // update under +-{{0, -i}, {i, 0}}
-
1436  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
-
1437  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
-
1438  stateVecReal[indexLo] = conjFac * -stateImagUp;
-
1439  stateVecImag[indexLo] = conjFac * stateRealUp;
-
1440  }
-
1441 }
-
1442 
-
1443 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
1444 {
-
1445  int conjFactor = 1;
-
1446  int threadsPerCUDABlock, CUDABlocks;
-
1447  threadsPerCUDABlock = 128;
-
1448  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1449  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1450 }
-
1451 
-
1452 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
1453 {
-
1454  int conjFactor = -1;
-
1455  int threadsPerCUDABlock, CUDABlocks;
-
1456  threadsPerCUDABlock = 128;
-
1457  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1458  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
-
1459 }
-
1460 
-
1461 __global__ void statevec_phaseShiftByTermKernel(Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle) {
+
1368 __global__ void statevec_pauliYKernel(Qureg qureg, int targetQubit, int conjFac){
+
1369 
+
1370  long long int sizeHalfBlock = 1LL << targetQubit;
+
1371  long long int sizeBlock = 2LL * sizeHalfBlock;
+
1372  long long int numTasks = qureg.numAmpsPerChunk >> 1;
+
1373  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1374  if (thisTask>=numTasks) return;
+
1375 
+
1376  long long int thisBlock = thisTask / sizeHalfBlock;
+
1377  long long int indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1378  long long int indexLo = indexUp + sizeHalfBlock;
+
1379  qreal stateRealUp, stateImagUp;
+
1380 
+
1381  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1382  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1383  stateRealUp = stateVecReal[indexUp];
+
1384  stateImagUp = stateVecImag[indexUp];
+
1385 
+
1386  // update under +-{{0, -i}, {i, 0}}
+
1387  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
1388  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
1389  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
1390  stateVecImag[indexLo] = conjFac * stateRealUp;
+
1391 }
+
1392 
+
1393 void statevec_pauliY(Qureg qureg, int targetQubit)
+
1394 {
+
1395  int threadsPerCUDABlock, CUDABlocks;
+
1396  threadsPerCUDABlock = 128;
+
1397  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1398  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, 1);
+
1399 }
+
1400 
+
1401 void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
1402 {
+
1403  int threadsPerCUDABlock, CUDABlocks;
+
1404  threadsPerCUDABlock = 128;
+
1405  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1406  statevec_pauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, -1);
+
1407 }
+
1408 
+
1409 __global__ void statevec_controlledPauliYKernel(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
+
1410 {
+
1411  long long int index;
+
1412  long long int sizeBlock, sizeHalfBlock;
+
1413  long long int stateVecSize;
+
1414  int controlBit;
+
1415 
+
1416  qreal stateRealUp, stateImagUp;
+
1417  long long int thisBlock, indexUp, indexLo;
+
1418  sizeHalfBlock = 1LL << targetQubit;
+
1419  sizeBlock = 2LL * sizeHalfBlock;
+
1420 
+
1421  stateVecSize = qureg.numAmpsPerChunk;
+
1422  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1423  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1424 
+
1425  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1426  if (index>=(stateVecSize>>1)) return;
+
1427  thisBlock = index / sizeHalfBlock;
+
1428  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
+
1429  indexLo = indexUp + sizeHalfBlock;
+
1430 
+
1431  controlBit = extractBit(controlQubit, indexUp);
+
1432  if (controlBit){
+
1433 
+
1434  stateRealUp = stateVecReal[indexUp];
+
1435  stateImagUp = stateVecImag[indexUp];
+
1436 
+
1437  // update under +-{{0, -i}, {i, 0}}
+
1438  stateVecReal[indexUp] = conjFac * stateVecImag[indexLo];
+
1439  stateVecImag[indexUp] = conjFac * -stateVecReal[indexLo];
+
1440  stateVecReal[indexLo] = conjFac * -stateImagUp;
+
1441  stateVecImag[indexLo] = conjFac * stateRealUp;
+
1442  }
+
1443 }
+
1444 
+
1445 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
1446 {
+
1447  int conjFactor = 1;
+
1448  int threadsPerCUDABlock, CUDABlocks;
+
1449  threadsPerCUDABlock = 128;
+
1450  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1451  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
+
1452 }
+
1453 
+
1454 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
1455 {
+
1456  int conjFactor = -1;
+
1457  int threadsPerCUDABlock, CUDABlocks;
+
1458  threadsPerCUDABlock = 128;
+
1459  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1460  statevec_controlledPauliYKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit, conjFactor);
+
1461 }
1462 
-
1463  long long int sizeBlock, sizeHalfBlock;
-
1464  long long int thisBlock, indexUp,indexLo;
-
1465 
-
1466  qreal stateRealLo, stateImagLo;
-
1467  long long int thisTask;
-
1468  long long int numTasks = qureg.numAmpsPerChunk >> 1;
-
1469 
-
1470  sizeHalfBlock = 1LL << targetQubit;
-
1471  sizeBlock = 2LL * sizeHalfBlock;
-
1472 
-
1473  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1474  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1475 
-
1476  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1477  if (thisTask>=numTasks) return;
-
1478  thisBlock = thisTask / sizeHalfBlock;
-
1479  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1480  indexLo = indexUp + sizeHalfBlock;
-
1481 
-
1482  stateRealLo = stateVecReal[indexLo];
-
1483  stateImagLo = stateVecImag[indexLo];
-
1484 
-
1485  stateVecReal[indexLo] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1486  stateVecImag[indexLo] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1487 }
-
1488 
-
1489 void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
-
1490 {
-
1491  qreal cosAngle = term.real;
-
1492  qreal sinAngle = term.imag;
-
1493 
-
1494  int threadsPerCUDABlock, CUDABlocks;
-
1495  threadsPerCUDABlock = 128;
-
1496  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1497  statevec_phaseShiftByTermKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, cosAngle, sinAngle);
-
1498 }
-
1499 
-
1500 __global__ void statevec_controlledPhaseShiftKernel(Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
-
1501 {
-
1502  long long int index;
-
1503  long long int stateVecSize;
-
1504  int bit1, bit2;
-
1505  qreal stateRealLo, stateImagLo;
-
1506 
-
1507  stateVecSize = qureg.numAmpsPerChunk;
-
1508  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1509  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1510 
-
1511  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1512  if (index>=stateVecSize) return;
-
1513 
-
1514  bit1 = extractBit (idQubit1, index);
-
1515  bit2 = extractBit (idQubit2, index);
-
1516  if (bit1 && bit2) {
-
1517  stateRealLo = stateVecReal[index];
-
1518  stateImagLo = stateVecImag[index];
-
1519 
-
1520  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1521  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1522  }
-
1523 }
-
1524 
-
1525 void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
-
1526 {
-
1527  qreal cosAngle = cos(angle);
-
1528  qreal sinAngle = sin(angle);
-
1529 
-
1530  int threadsPerCUDABlock, CUDABlocks;
-
1531  threadsPerCUDABlock = 128;
-
1532  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1533  statevec_controlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2, cosAngle, sinAngle);
-
1534 }
-
1535 
-
1536 __global__ void statevec_multiControlledPhaseShiftKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle) {
-
1537  qreal stateRealLo, stateImagLo;
-
1538  long long int index;
-
1539  long long int stateVecSize;
-
1540 
-
1541  stateVecSize = qureg.numAmpsPerChunk;
-
1542  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1543  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1544 
-
1545  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1546  if (index>=stateVecSize) return;
-
1547 
-
1548  if (mask == (mask & index) ){
-
1549  stateRealLo = stateVecReal[index];
-
1550  stateImagLo = stateVecImag[index];
-
1551  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
1552  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
1553  }
-
1554 }
-
1555 
-
1556 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
-
1557 {
-
1558  qreal cosAngle = cos(angle);
-
1559  qreal sinAngle = sin(angle);
-
1560 
-
1561  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1562 
-
1563  int threadsPerCUDABlock, CUDABlocks;
-
1564  threadsPerCUDABlock = 128;
-
1565  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1566  statevec_multiControlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1567 }
-
1568 
-
1569 __global__ void statevec_multiRotateZKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle) {
-
1570 
-
1571  long long int stateVecSize = qureg.numAmpsPerChunk;
-
1572  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
1573  if (index>=stateVecSize) return;
-
1574 
-
1575  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1576  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1577 
-
1578  int fac = getBitMaskParity(mask & index)? -1 : 1;
-
1579  qreal stateReal = stateVecReal[index];
-
1580  qreal stateImag = stateVecImag[index];
-
1581 
-
1582  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
1583  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
1584 }
-
1585 
-
1586 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
-
1587 {
-
1588  qreal cosAngle = cos(angle/2.0);
-
1589  qreal sinAngle = sin(angle/2.0);
-
1590 
-
1591  int threadsPerCUDABlock, CUDABlocks;
-
1592  threadsPerCUDABlock = 128;
-
1593  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1594  statevec_multiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
-
1595 }
-
1596 
-
1597 __global__ void statevec_multiControlledMultiRotateZKernel(Qureg qureg, long long int ctrlMask, long long int targMask, qreal cosAngle, qreal sinAngle) {
-
1598 
-
1599  long long int stateVecSize = qureg.numAmpsPerChunk;
-
1600  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
1601  if (index>=stateVecSize) return;
-
1602 
-
1603  // amplitudes corresponding to control qubits not all-in-one are unmodified
-
1604  if (ctrlMask && ((ctrlMask & index) != ctrlMask))
-
1605  return;
-
1606 
-
1607  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1608  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1609 
-
1610  // avoid warp divergence, setting fac = +- 1
-
1611  int fac = 1-2*getBitMaskParity(targMask & index);
-
1612  qreal stateReal = stateVecReal[index];
-
1613  qreal stateImag = stateVecImag[index];
-
1614 
-
1615  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
1616  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
1617 }
-
1618 
-
1619 void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
-
1620 {
-
1621  qreal cosAngle = cos(angle/2.0);
-
1622  qreal sinAngle = sin(angle/2.0);
-
1623 
-
1624  int threadsPerCUDABlock, CUDABlocks;
-
1625  threadsPerCUDABlock = 128;
-
1626  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1627  statevec_multiControlledMultiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, targMask, cosAngle, sinAngle);
-
1628 }
-
1629 
- -
1631 
-
1632  // computes the trace using Kahan summation
-
1633  qreal pTotal=0;
-
1634  qreal y, t, c;
-
1635  c = 0;
-
1636 
-
1637  long long int numCols = 1LL << qureg.numQubitsRepresented;
-
1638  long long diagIndex;
-
1639 
-
1640  copyStateFromGPU(qureg);
+
1463 __global__ void statevec_phaseShiftByTermKernel(Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle) {
+
1464 
+
1465  long long int sizeBlock, sizeHalfBlock;
+
1466  long long int thisBlock, indexUp,indexLo;
+
1467 
+
1468  qreal stateRealLo, stateImagLo;
+
1469  long long int thisTask;
+
1470  long long int numTasks = qureg.numAmpsPerChunk >> 1;
+
1471 
+
1472  sizeHalfBlock = 1LL << targetQubit;
+
1473  sizeBlock = 2LL * sizeHalfBlock;
+
1474 
+
1475  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1476  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1477 
+
1478  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1479  if (thisTask>=numTasks) return;
+
1480  thisBlock = thisTask / sizeHalfBlock;
+
1481  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1482  indexLo = indexUp + sizeHalfBlock;
+
1483 
+
1484  stateRealLo = stateVecReal[indexLo];
+
1485  stateImagLo = stateVecImag[indexLo];
+
1486 
+
1487  stateVecReal[indexLo] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
1488  stateVecImag[indexLo] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
1489 }
+
1490 
+
1491 void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
+
1492 {
+
1493  qreal cosAngle = term.real;
+
1494  qreal sinAngle = term.imag;
+
1495 
+
1496  int threadsPerCUDABlock, CUDABlocks;
+
1497  threadsPerCUDABlock = 128;
+
1498  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1499  statevec_phaseShiftByTermKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit, cosAngle, sinAngle);
+
1500 }
+
1501 
+
1502 __global__ void statevec_controlledPhaseShiftKernel(Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
+
1503 {
+
1504  long long int index;
+
1505  long long int stateVecSize;
+
1506  int bit1, bit2;
+
1507  qreal stateRealLo, stateImagLo;
+
1508 
+
1509  stateVecSize = qureg.numAmpsPerChunk;
+
1510  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1511  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1512 
+
1513  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1514  if (index>=stateVecSize) return;
+
1515 
+
1516  bit1 = extractBit (idQubit1, index);
+
1517  bit2 = extractBit (idQubit2, index);
+
1518  if (bit1 && bit2) {
+
1519  stateRealLo = stateVecReal[index];
+
1520  stateImagLo = stateVecImag[index];
+
1521 
+
1522  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
1523  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
1524  }
+
1525 }
+
1526 
+
1527 void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
+
1528 {
+
1529  qreal cosAngle = cos(angle);
+
1530  qreal sinAngle = sin(angle);
+
1531 
+
1532  int threadsPerCUDABlock, CUDABlocks;
+
1533  threadsPerCUDABlock = 128;
+
1534  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1535  statevec_controlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2, cosAngle, sinAngle);
+
1536 }
+
1537 
+
1538 __global__ void statevec_multiControlledPhaseShiftKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle) {
+
1539  qreal stateRealLo, stateImagLo;
+
1540  long long int index;
+
1541  long long int stateVecSize;
+
1542 
+
1543  stateVecSize = qureg.numAmpsPerChunk;
+
1544  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1545  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1546 
+
1547  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1548  if (index>=stateVecSize) return;
+
1549 
+
1550  if (mask == (mask & index) ){
+
1551  stateRealLo = stateVecReal[index];
+
1552  stateImagLo = stateVecImag[index];
+
1553  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
1554  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
1555  }
+
1556 }
+
1557 
+
1558 void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
+
1559 {
+
1560  qreal cosAngle = cos(angle);
+
1561  qreal sinAngle = sin(angle);
+
1562 
+
1563  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
1564 
+
1565  int threadsPerCUDABlock, CUDABlocks;
+
1566  threadsPerCUDABlock = 128;
+
1567  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1568  statevec_multiControlledPhaseShiftKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
+
1569 }
+
1570 
+
1571 __global__ void statevec_multiRotateZKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle) {
+
1572 
+
1573  long long int stateVecSize = qureg.numAmpsPerChunk;
+
1574  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
1575  if (index>=stateVecSize) return;
+
1576 
+
1577  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1578  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1579 
+
1580  int fac = getBitMaskParity(mask & index)? -1 : 1;
+
1581  qreal stateReal = stateVecReal[index];
+
1582  qreal stateImag = stateVecImag[index];
+
1583 
+
1584  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
1585  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
1586 }
+
1587 
+
1588 void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
+
1589 {
+
1590  qreal cosAngle = cos(angle/2.0);
+
1591  qreal sinAngle = sin(angle/2.0);
+
1592 
+
1593  int threadsPerCUDABlock, CUDABlocks;
+
1594  threadsPerCUDABlock = 128;
+
1595  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1596  statevec_multiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask, cosAngle, sinAngle);
+
1597 }
+
1598 
+
1599 __global__ void statevec_multiControlledMultiRotateZKernel(Qureg qureg, long long int ctrlMask, long long int targMask, qreal cosAngle, qreal sinAngle) {
+
1600 
+
1601  long long int stateVecSize = qureg.numAmpsPerChunk;
+
1602  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
1603  if (index>=stateVecSize) return;
+
1604 
+
1605  // amplitudes corresponding to control qubits not all-in-one are unmodified
+
1606  if (ctrlMask && ((ctrlMask & index) != ctrlMask))
+
1607  return;
+
1608 
+
1609  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1610  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1611 
+
1612  // avoid warp divergence, setting fac = +- 1
+
1613  int fac = 1-2*getBitMaskParity(targMask & index);
+
1614  qreal stateReal = stateVecReal[index];
+
1615  qreal stateImag = stateVecImag[index];
+
1616 
+
1617  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
1618  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
1619 }
+
1620 
+
1621 void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
+
1622 {
+
1623  qreal cosAngle = cos(angle/2.0);
+
1624  qreal sinAngle = sin(angle/2.0);
+
1625 
+
1626  int threadsPerCUDABlock, CUDABlocks;
+
1627  threadsPerCUDABlock = 128;
+
1628  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1629  statevec_multiControlledMultiRotateZKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, ctrlMask, targMask, cosAngle, sinAngle);
+
1630 }
+
1631 
+ +
1633 
+
1634  // computes the trace using Kahan summation
+
1635  qreal pTotal=0;
+
1636  qreal y, t, c;
+
1637  c = 0;
+
1638 
+
1639  long long int numCols = 1LL << qureg.numQubitsRepresented;
+
1640  long long diagIndex;
1641 
-
1642  for (int col=0; col< numCols; col++) {
-
1643  diagIndex = col*(numCols + 1);
-
1644  y = qureg.stateVec.real[diagIndex] - c;
-
1645  t = pTotal + y;
-
1646  c = ( t - pTotal ) - y; // brackets are important
-
1647  pTotal = t;
-
1648  }
-
1649 
-
1650  return pTotal;
-
1651 }
-
1652 
- -
1654  /* IJB - implemented using Kahan summation for greater accuracy at a slight floating
-
1655  point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
-
1656  /* Don't change the bracketing in this routine! */
-
1657  qreal pTotal=0;
-
1658  qreal y, t, c;
-
1659  long long int index;
-
1660  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
-
1661 
-
1662  copyStateFromGPU(qureg);
+
1642  copyStateFromGPU(qureg);
+
1643 
+
1644  for (int col=0; col< numCols; col++) {
+
1645  diagIndex = col*(numCols + 1);
+
1646  y = qureg.stateVec.real[diagIndex] - c;
+
1647  t = pTotal + y;
+
1648  c = ( t - pTotal ) - y; // brackets are important
+
1649  pTotal = t;
+
1650  }
+
1651 
+
1652  return pTotal;
+
1653 }
+
1654 
+ +
1656  /* IJB - implemented using Kahan summation for greater accuracy at a slight floating
+
1657  point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm */
+
1658  /* Don't change the bracketing in this routine! */
+
1659  qreal pTotal=0;
+
1660  qreal y, t, c;
+
1661  long long int index;
+
1662  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
1663 
-
1664  c = 0.0;
-
1665  for (index=0; index<numAmpsPerRank; index++){
-
1666  /* Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan */
-
1667  // pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index];
-
1668  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
-
1669  t = pTotal + y;
-
1670  c = ( t - pTotal ) - y;
-
1671  pTotal = t;
-
1672 
-
1673  /* Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan */
-
1674  //pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index];
-
1675  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
-
1676  t = pTotal + y;
-
1677  c = ( t - pTotal ) - y;
-
1678  pTotal = t;
-
1679 
-
1680 
-
1681  }
-
1682  return pTotal;
-
1683 }
-
1684 
-
1685 __global__ void statevec_controlledPhaseFlipKernel(Qureg qureg, int idQubit1, int idQubit2)
-
1686 {
-
1687  long long int index;
-
1688  long long int stateVecSize;
-
1689  int bit1, bit2;
-
1690 
-
1691  stateVecSize = qureg.numAmpsPerChunk;
-
1692  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1693  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1694 
-
1695  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1696  if (index>=stateVecSize) return;
-
1697 
-
1698  bit1 = extractBit (idQubit1, index);
-
1699  bit2 = extractBit (idQubit2, index);
-
1700  if (bit1 && bit2) {
-
1701  stateVecReal [index] = - stateVecReal [index];
-
1702  stateVecImag [index] = - stateVecImag [index];
-
1703  }
-
1704 }
-
1705 
-
1706 void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
-
1707 {
-
1708  int threadsPerCUDABlock, CUDABlocks;
-
1709  threadsPerCUDABlock = 128;
-
1710  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1711  statevec_controlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2);
-
1712 }
-
1713 
-
1714 __global__ void statevec_multiControlledPhaseFlipKernel(Qureg qureg, long long int mask)
-
1715 {
-
1716  long long int index;
-
1717  long long int stateVecSize;
-
1718 
-
1719  stateVecSize = qureg.numAmpsPerChunk;
-
1720  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1721  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1722 
-
1723  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1724  if (index>=stateVecSize) return;
-
1725 
-
1726  if (mask == (mask & index) ){
-
1727  stateVecReal [index] = - stateVecReal [index];
-
1728  stateVecImag [index] = - stateVecImag [index];
-
1729  }
-
1730 }
-
1731 
-
1732 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
-
1733 {
-
1734  int threadsPerCUDABlock, CUDABlocks;
-
1735  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
1736  threadsPerCUDABlock = 128;
-
1737  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1738  statevec_multiControlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask);
-
1739 }
-
1740 
-
1741 __global__ void statevec_swapQubitAmpsKernel(Qureg qureg, int qb1, int qb2) {
+
1664  copyStateFromGPU(qureg);
+
1665 
+
1666  c = 0.0;
+
1667  for (index=0; index<numAmpsPerRank; index++){
+
1668  /* Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan */
+
1669  // pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index];
+
1670  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
+
1671  t = pTotal + y;
+
1672  c = ( t - pTotal ) - y;
+
1673  pTotal = t;
+
1674 
+
1675  /* Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan */
+
1676  //pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index];
+
1677  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
+
1678  t = pTotal + y;
+
1679  c = ( t - pTotal ) - y;
+
1680  pTotal = t;
+
1681 
+
1682 
+
1683  }
+
1684  return pTotal;
+
1685 }
+
1686 
+
1687 __global__ void statevec_controlledPhaseFlipKernel(Qureg qureg, int idQubit1, int idQubit2)
+
1688 {
+
1689  long long int index;
+
1690  long long int stateVecSize;
+
1691  int bit1, bit2;
+
1692 
+
1693  stateVecSize = qureg.numAmpsPerChunk;
+
1694  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1695  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1696 
+
1697  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1698  if (index>=stateVecSize) return;
+
1699 
+
1700  bit1 = extractBit (idQubit1, index);
+
1701  bit2 = extractBit (idQubit2, index);
+
1702  if (bit1 && bit2) {
+
1703  stateVecReal [index] = - stateVecReal [index];
+
1704  stateVecImag [index] = - stateVecImag [index];
+
1705  }
+
1706 }
+
1707 
+
1708 void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
+
1709 {
+
1710  int threadsPerCUDABlock, CUDABlocks;
+
1711  threadsPerCUDABlock = 128;
+
1712  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1713  statevec_controlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, idQubit1, idQubit2);
+
1714 }
+
1715 
+
1716 __global__ void statevec_multiControlledPhaseFlipKernel(Qureg qureg, long long int mask)
+
1717 {
+
1718  long long int index;
+
1719  long long int stateVecSize;
+
1720 
+
1721  stateVecSize = qureg.numAmpsPerChunk;
+
1722  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1723  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1724 
+
1725  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1726  if (index>=stateVecSize) return;
+
1727 
+
1728  if (mask == (mask & index) ){
+
1729  stateVecReal [index] = - stateVecReal [index];
+
1730  stateVecImag [index] = - stateVecImag [index];
+
1731  }
+
1732 }
+
1733 
+
1734 void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
+
1735 {
+
1736  int threadsPerCUDABlock, CUDABlocks;
+
1737  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
1738  threadsPerCUDABlock = 128;
+
1739  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1740  statevec_multiControlledPhaseFlipKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, mask);
+
1741 }
1742 
-
1743  qreal *reVec = qureg.deviceStateVec.real;
-
1744  qreal *imVec = qureg.deviceStateVec.imag;
-
1745 
-
1746  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
-
1747  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1748  if (thisTask>=numTasks) return;
-
1749 
-
1750  long long int ind00, ind01, ind10;
-
1751  qreal re01, re10, im01, im10;
-
1752 
-
1753  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
-
1754  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
-
1755  ind01 = flipBit(ind00, qb1);
-
1756  ind10 = flipBit(ind00, qb2);
-
1757 
-
1758  // extract statevec amplitudes
-
1759  re01 = reVec[ind01]; im01 = imVec[ind01];
-
1760  re10 = reVec[ind10]; im10 = imVec[ind10];
-
1761 
-
1762  // swap 01 and 10 amps
-
1763  reVec[ind01] = re10; reVec[ind10] = re01;
-
1764  imVec[ind01] = im10; imVec[ind10] = im01;
-
1765 }
-
1766 
-
1767 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
1768 {
-
1769  int threadsPerCUDABlock, CUDABlocks;
-
1770  threadsPerCUDABlock = 128;
-
1771  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock);
-
1772  statevec_swapQubitAmpsKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, qb1, qb2);
-
1773 }
-
1774 
-
1775 __global__ void statevec_hadamardKernel (Qureg qureg, int targetQubit){
-
1776  // ----- sizes
-
1777  long long int sizeBlock, // size of blocks
-
1778  sizeHalfBlock; // size of blocks halved
-
1779  // ----- indices
-
1780  long long int thisBlock, // current block
-
1781  indexUp,indexLo; // current index and corresponding index in lower half block
-
1782 
-
1783  // ----- temp variables
-
1784  qreal stateRealUp,stateRealLo, // storage for previous state values
-
1785  stateImagUp,stateImagLo; // (used in updates)
-
1786  // ----- temp variables
-
1787  long long int thisTask; // task based approach for expose loop with small granularity
-
1788  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
1789 
-
1790  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1791  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1792 
-
1793  // ---------------------------------------------------------------- //
-
1794  // rotate //
+
1743 __global__ void statevec_swapQubitAmpsKernel(Qureg qureg, int qb1, int qb2) {
+
1744 
+
1745  qreal *reVec = qureg.deviceStateVec.real;
+
1746  qreal *imVec = qureg.deviceStateVec.imag;
+
1747 
+
1748  long long int numTasks = qureg.numAmpsPerChunk >> 2; // each iteration updates 2 amps and skips 2 amps
+
1749  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1750  if (thisTask>=numTasks) return;
+
1751 
+
1752  long long int ind00, ind01, ind10;
+
1753  qreal re01, re10, im01, im10;
+
1754 
+
1755  // determine ind00 of |..0..0..>, |..0..1..> and |..1..0..>
+
1756  ind00 = insertTwoZeroBits(thisTask, qb1, qb2);
+
1757  ind01 = flipBit(ind00, qb1);
+
1758  ind10 = flipBit(ind00, qb2);
+
1759 
+
1760  // extract statevec amplitudes
+
1761  re01 = reVec[ind01]; im01 = imVec[ind01];
+
1762  re10 = reVec[ind10]; im10 = imVec[ind10];
+
1763 
+
1764  // swap 01 and 10 amps
+
1765  reVec[ind01] = re10; reVec[ind10] = re01;
+
1766  imVec[ind01] = im10; imVec[ind10] = im01;
+
1767 }
+
1768 
+
1769 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
1770 {
+
1771  int threadsPerCUDABlock, CUDABlocks;
+
1772  threadsPerCUDABlock = 128;
+
1773  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>2)/threadsPerCUDABlock);
+
1774  statevec_swapQubitAmpsKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, qb1, qb2);
+
1775 }
+
1776 
+
1777 __global__ void statevec_hadamardKernel (Qureg qureg, int targetQubit){
+
1778  // ----- sizes
+
1779  long long int sizeBlock, // size of blocks
+
1780  sizeHalfBlock; // size of blocks halved
+
1781  // ----- indices
+
1782  long long int thisBlock, // current block
+
1783  indexUp,indexLo; // current index and corresponding index in lower half block
+
1784 
+
1785  // ----- temp variables
+
1786  qreal stateRealUp,stateRealLo, // storage for previous state values
+
1787  stateImagUp,stateImagLo; // (used in updates)
+
1788  // ----- temp variables
+
1789  long long int thisTask; // task based approach for expose loop with small granularity
+
1790  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
1791 
+
1792  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1793  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1794 
1795  // ---------------------------------------------------------------- //
-
1796 
-
1798  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1799  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1800 
-
1801  qreal recRoot2 = 1.0/sqrt(2.0);
+
1796  // rotate //
+
1797  // ---------------------------------------------------------------- //
+
1798 
+
1800  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1801  qreal *stateVecImag = qureg.deviceStateVec.imag;
1802 
-
1803  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1804  if (thisTask>=numTasks) return;
-
1805 
-
1806  thisBlock = thisTask / sizeHalfBlock;
-
1807  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1808  indexLo = indexUp + sizeHalfBlock;
-
1809 
-
1810  // store current state vector values in temp variables
-
1811  stateRealUp = stateVecReal[indexUp];
-
1812  stateImagUp = stateVecImag[indexUp];
-
1813 
-
1814  stateRealLo = stateVecReal[indexLo];
-
1815  stateImagLo = stateVecImag[indexLo];
-
1816 
-
1817  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
-
1818  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
-
1819 
-
1820  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
-
1821  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
-
1822 }
-
1823 
-
1824 void statevec_hadamard(Qureg qureg, int targetQubit)
-
1825 {
-
1826  int threadsPerCUDABlock, CUDABlocks;
-
1827  threadsPerCUDABlock = 128;
-
1828  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
1829  statevec_hadamardKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
-
1830 }
-
1831 
-
1832 __global__ void statevec_controlledNotKernel(Qureg qureg, int controlQubit, int targetQubit)
-
1833 {
-
1834  long long int index;
-
1835  long long int sizeBlock, // size of blocks
-
1836  sizeHalfBlock; // size of blocks halved
-
1837  long long int stateVecSize;
-
1838  int controlBit;
-
1839 
-
1840  // ----- temp variables
-
1841  qreal stateRealUp, // storage for previous state values
-
1842  stateImagUp; // (used in updates)
-
1843  long long int thisBlock, // current block
-
1844  indexUp,indexLo; // current index and corresponding index in lower half block
-
1845  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
-
1846  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
-
1847 
-
1848  stateVecSize = qureg.numAmpsPerChunk;
-
1849  qreal *stateVecReal = qureg.deviceStateVec.real;
-
1850  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
1851 
-
1852  index = blockIdx.x*blockDim.x + threadIdx.x;
-
1853  if (index>=(stateVecSize>>1)) return;
-
1854  thisBlock = index / sizeHalfBlock;
-
1855  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
-
1856  indexLo = indexUp + sizeHalfBlock;
-
1857 
-
1858  controlBit = extractBit(controlQubit, indexUp);
-
1859  if (controlBit){
-
1860  stateRealUp = stateVecReal[indexUp];
-
1861  stateImagUp = stateVecImag[indexUp];
-
1862 
-
1863  stateVecReal[indexUp] = stateVecReal[indexLo];
-
1864  stateVecImag[indexUp] = stateVecImag[indexLo];
-
1865 
-
1866  stateVecReal[indexLo] = stateRealUp;
-
1867  stateVecImag[indexLo] = stateImagUp;
-
1868  }
-
1869 }
-
1870 
-
1871 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
1872 {
-
1873  int threadsPerCUDABlock, CUDABlocks;
-
1874  threadsPerCUDABlock = 128;
-
1875  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
1876  statevec_controlledNotKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit);
-
1877 }
-
1878 
-
1879 __global__ void statevec_multiControlledMultiQubitNotKernel(Qureg qureg, int ctrlMask, int targMask) {
-
1880 
-
1881  qreal* stateRe = qureg.deviceStateVec.real;
-
1882  qreal* stateIm = qureg.deviceStateVec.imag;
-
1883 
-
1884  // althouugh each thread swaps/updates two amplitudes, we still invoke one thread per amp
-
1885  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
1886  if (ampInd >= qureg.numAmpsPerChunk)
-
1887  return;
-
1888 
-
1889  // modify amplitudes only if control qubits are 1 for this state
-
1890  if (ctrlMask && ((ctrlMask & ampInd) != ctrlMask))
-
1891  return;
-
1892 
-
1893  long long int mateInd = ampInd ^ targMask;
+
1803  qreal recRoot2 = 1.0/sqrt(2.0);
+
1804 
+
1805  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1806  if (thisTask>=numTasks) return;
+
1807 
+
1808  thisBlock = thisTask / sizeHalfBlock;
+
1809  indexUp = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1810  indexLo = indexUp + sizeHalfBlock;
+
1811 
+
1812  // store current state vector values in temp variables
+
1813  stateRealUp = stateVecReal[indexUp];
+
1814  stateImagUp = stateVecImag[indexUp];
+
1815 
+
1816  stateRealLo = stateVecReal[indexLo];
+
1817  stateImagLo = stateVecImag[indexLo];
+
1818 
+
1819  stateVecReal[indexUp] = recRoot2*(stateRealUp + stateRealLo);
+
1820  stateVecImag[indexUp] = recRoot2*(stateImagUp + stateImagLo);
+
1821 
+
1822  stateVecReal[indexLo] = recRoot2*(stateRealUp - stateRealLo);
+
1823  stateVecImag[indexLo] = recRoot2*(stateImagUp - stateImagLo);
+
1824 }
+
1825 
+
1826 void statevec_hadamard(Qureg qureg, int targetQubit)
+
1827 {
+
1828  int threadsPerCUDABlock, CUDABlocks;
+
1829  threadsPerCUDABlock = 128;
+
1830  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
1831  statevec_hadamardKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, targetQubit);
+
1832 }
+
1833 
+
1834 __global__ void statevec_controlledNotKernel(Qureg qureg, int controlQubit, int targetQubit)
+
1835 {
+
1836  long long int index;
+
1837  long long int sizeBlock, // size of blocks
+
1838  sizeHalfBlock; // size of blocks halved
+
1839  long long int stateVecSize;
+
1840  int controlBit;
+
1841 
+
1842  // ----- temp variables
+
1843  qreal stateRealUp, // storage for previous state values
+
1844  stateImagUp; // (used in updates)
+
1845  long long int thisBlock, // current block
+
1846  indexUp,indexLo; // current index and corresponding index in lower half block
+
1847  sizeHalfBlock = 1LL << targetQubit; // size of blocks halved
+
1848  sizeBlock = 2LL * sizeHalfBlock; // size of blocks
+
1849 
+
1850  stateVecSize = qureg.numAmpsPerChunk;
+
1851  qreal *stateVecReal = qureg.deviceStateVec.real;
+
1852  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
1853 
+
1854  index = blockIdx.x*blockDim.x + threadIdx.x;
+
1855  if (index>=(stateVecSize>>1)) return;
+
1856  thisBlock = index / sizeHalfBlock;
+
1857  indexUp = thisBlock*sizeBlock + index%sizeHalfBlock;
+
1858  indexLo = indexUp + sizeHalfBlock;
+
1859 
+
1860  controlBit = extractBit(controlQubit, indexUp);
+
1861  if (controlBit){
+
1862  stateRealUp = stateVecReal[indexUp];
+
1863  stateImagUp = stateVecImag[indexUp];
+
1864 
+
1865  stateVecReal[indexUp] = stateVecReal[indexLo];
+
1866  stateVecImag[indexUp] = stateVecImag[indexLo];
+
1867 
+
1868  stateVecReal[indexLo] = stateRealUp;
+
1869  stateVecImag[indexLo] = stateImagUp;
+
1870  }
+
1871 }
+
1872 
+
1873 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
1874 {
+
1875  int threadsPerCUDABlock, CUDABlocks;
+
1876  threadsPerCUDABlock = 128;
+
1877  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
1878  statevec_controlledNotKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, controlQubit, targetQubit);
+
1879 }
+
1880 
+
1881 __global__ void statevec_multiControlledMultiQubitNotKernel(Qureg qureg, int ctrlMask, int targMask) {
+
1882 
+
1883  qreal* stateRe = qureg.deviceStateVec.real;
+
1884  qreal* stateIm = qureg.deviceStateVec.imag;
+
1885 
+
1886  // althouugh each thread swaps/updates two amplitudes, we still invoke one thread per amp
+
1887  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
1888  if (ampInd >= qureg.numAmpsPerChunk)
+
1889  return;
+
1890 
+
1891  // modify amplitudes only if control qubits are 1 for this state
+
1892  if (ctrlMask && ((ctrlMask & ampInd) != ctrlMask))
+
1893  return;
1894 
-
1895  // if the mate is lower index, another thread is handling it
-
1896  if (mateInd < ampInd)
-
1897  return;
-
1898 
-
1899  /* it may seem wasteful to spawn more threads than are needed, and abort
-
1900  * half of them due to the amp pairing above (and potentially abort
-
1901  * an exponential number due to ctrlMask). however, since we are moving
-
1902  * global memory directly in a potentially non-contiguous fashoin, this
-
1903  * method is likely to be memory bandwidth bottlenecked anyway
-
1904  */
-
1905 
-
1906  qreal mateRe = stateRe[mateInd];
-
1907  qreal mateIm = stateIm[mateInd];
-
1908 
-
1909  // swap amp with mate
-
1910  stateRe[mateInd] = stateRe[ampInd];
-
1911  stateIm[mateInd] = stateIm[ampInd];
-
1912  stateRe[ampInd] = mateRe;
-
1913  stateIm[ampInd] = mateIm;
-
1914 }
-
1915 
-
1916 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) {
-
1917 
-
1918  int numThreadsPerBlock = 128;
-
1919  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
-
1920  statevec_multiControlledMultiQubitNotKernel<<<numBlocks, numThreadsPerBlock>>>(qureg, ctrlMask, targMask);
-
1921 }
-
1922 
-
1923 __device__ __host__ unsigned int log2Int( unsigned int x )
-
1924 {
-
1925  unsigned int ans = 0 ;
-
1926  while( x>>=1 ) ans++;
-
1927  return ans ;
-
1928 }
-
1929 
-
1930 __device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length){
-
1931  int i, l, r;
-
1932  int threadMax, maxDepth;
-
1933  threadMax = length/2;
-
1934  maxDepth = log2Int(length/2);
-
1935 
-
1936  for (i=0; i<maxDepth+1; i++){
-
1937  if (threadIdx.x<threadMax){
-
1938  l = threadIdx.x;
-
1939  r = l + threadMax;
-
1940  arrayIn[l] = arrayIn[r] + arrayIn[l];
-
1941  }
-
1942  threadMax = threadMax >> 1;
-
1943  __syncthreads(); // optimise -- use warp shuffle instead
-
1944  }
-
1945 
-
1946  if (threadIdx.x==0) reducedArray[blockIdx.x] = arrayIn[0];
-
1947 }
-
1948 
-
1949 __global__ void copySharedReduceBlock(qreal*arrayIn, qreal *reducedArray, int length){
-
1950  extern __shared__ qreal tempReductionArray[];
-
1951  int blockOffset = blockIdx.x*length;
-
1952  tempReductionArray[threadIdx.x*2] = arrayIn[blockOffset + threadIdx.x*2];
-
1953  tempReductionArray[threadIdx.x*2+1] = arrayIn[blockOffset + threadIdx.x*2+1];
-
1954  __syncthreads();
-
1955  reduceBlock(tempReductionArray, reducedArray, length);
-
1956 }
-
1957 
- -
1959  Qureg qureg, int measureQubit, qreal *reducedArray
-
1960 ) {
-
1961  // run by each thread
-
1962  // use of block here refers to contiguous amplitudes where measureQubit = 0,
-
1963  // (then =1) and NOT the CUDA block, which is the partitioning of CUDA threads
-
1964 
-
1965  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1966  long long int numTasks = densityDim >> 1;
-
1967  long long int sizeHalfBlock = 1LL << (measureQubit);
-
1968  long long int sizeBlock = 2LL * sizeHalfBlock;
-
1969 
-
1970  long long int thisBlock; // which block this thread is processing
-
1971  long long int thisTask; // which part of the block this thread is processing
-
1972  long long int basisIndex; // index of this thread's computational basis state
-
1973  long long int densityIndex; // " " index of |basis><basis| in the flat density matrix
-
1974 
-
1975  // array of each thread's collected probability, to be summed
-
1976  extern __shared__ qreal tempReductionArray[];
-
1977 
-
1978  // figure out which density matrix prob that this thread is assigned
-
1979  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
1980  if (thisTask>=numTasks) return;
-
1981  thisBlock = thisTask / sizeHalfBlock;
-
1982  basisIndex = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
1983  densityIndex = (densityDim + 1) * basisIndex;
-
1984 
-
1985  // record the probability in the CUDA-BLOCK-wide array
-
1986  qreal prob = qureg.deviceStateVec.real[densityIndex]; // im[densityIndex] assumed ~ 0
-
1987  tempReductionArray[threadIdx.x] = prob;
-
1988 
-
1989  // sum the probs collected by this CUDA-BLOCK's threads into a per-CUDA-BLOCK array
-
1990  __syncthreads();
-
1991  if (threadIdx.x<blockDim.x/2){
-
1992  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
1993  }
-
1994 }
-
1995 
- -
1997  Qureg qureg, int measureQubit, qreal *reducedArray
-
1998 ) {
-
1999  // ----- sizes
-
2000  long long int sizeBlock, // size of blocks
-
2001  sizeHalfBlock; // size of blocks halved
-
2002  // ----- indices
-
2003  long long int thisBlock, // current block
-
2004  index; // current index for first half block
-
2005  // ----- temp variables
-
2006  long long int thisTask; // task based approach for expose loop with small granularity
-
2007  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2008  // (good for shared memory parallelism)
-
2009 
-
2010  extern __shared__ qreal tempReductionArray[];
+
1895  long long int mateInd = ampInd ^ targMask;
+
1896 
+
1897  // if the mate is lower index, another thread is handling it
+
1898  if (mateInd < ampInd)
+
1899  return;
+
1900 
+
1901  /* it may seem wasteful to spawn more threads than are needed, and abort
+
1902  * half of them due to the amp pairing above (and potentially abort
+
1903  * an exponential number due to ctrlMask). however, since we are moving
+
1904  * global memory directly in a potentially non-contiguous fashoin, this
+
1905  * method is likely to be memory bandwidth bottlenecked anyway
+
1906  */
+
1907 
+
1908  qreal mateRe = stateRe[mateInd];
+
1909  qreal mateIm = stateIm[mateInd];
+
1910 
+
1911  // swap amp with mate
+
1912  stateRe[mateInd] = stateRe[ampInd];
+
1913  stateIm[mateInd] = stateIm[ampInd];
+
1914  stateRe[ampInd] = mateRe;
+
1915  stateIm[ampInd] = mateIm;
+
1916 }
+
1917 
+
1918 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) {
+
1919 
+
1920  int numThreadsPerBlock = 128;
+
1921  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
+
1922  statevec_multiControlledMultiQubitNotKernel<<<numBlocks, numThreadsPerBlock>>>(qureg, ctrlMask, targMask);
+
1923 }
+
1924 
+
1925 __device__ __host__ unsigned int log2Int( unsigned int x )
+
1926 {
+
1927  unsigned int ans = 0 ;
+
1928  while( x>>=1 ) ans++;
+
1929  return ans ;
+
1930 }
+
1931 
+
1932 __device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length){
+
1933  int i, l, r;
+
1934  int threadMax, maxDepth;
+
1935  threadMax = length/2;
+
1936  maxDepth = log2Int(length/2);
+
1937 
+
1938  for (i=0; i<maxDepth+1; i++){
+
1939  if (threadIdx.x<threadMax){
+
1940  l = threadIdx.x;
+
1941  r = l + threadMax;
+
1942  arrayIn[l] = arrayIn[r] + arrayIn[l];
+
1943  }
+
1944  threadMax = threadMax >> 1;
+
1945  __syncthreads(); // optimise -- use warp shuffle instead
+
1946  }
+
1947 
+
1948  if (threadIdx.x==0) reducedArray[blockIdx.x] = arrayIn[0];
+
1949 }
+
1950 
+
1951 __global__ void copySharedReduceBlock(qreal*arrayIn, qreal *reducedArray, int length){
+
1952  extern __shared__ qreal tempReductionArray[];
+
1953  int blockOffset = blockIdx.x*length;
+
1954  tempReductionArray[threadIdx.x*2] = arrayIn[blockOffset + threadIdx.x*2];
+
1955  tempReductionArray[threadIdx.x*2+1] = arrayIn[blockOffset + threadIdx.x*2+1];
+
1956  __syncthreads();
+
1957  reduceBlock(tempReductionArray, reducedArray, length);
+
1958 }
+
1959 
+ +
1961  Qureg qureg, int measureQubit, qreal *reducedArray
+
1962 ) {
+
1963  // run by each thread
+
1964  // use of block here refers to contiguous amplitudes where measureQubit = 0,
+
1965  // (then =1) and NOT the CUDA block, which is the partitioning of CUDA threads
+
1966 
+
1967  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
1968  long long int numTasks = densityDim >> 1;
+
1969  long long int sizeHalfBlock = 1LL << (measureQubit);
+
1970  long long int sizeBlock = 2LL * sizeHalfBlock;
+
1971 
+
1972  long long int thisBlock; // which block this thread is processing
+
1973  long long int thisTask; // which part of the block this thread is processing
+
1974  long long int basisIndex; // index of this thread's computational basis state
+
1975  long long int densityIndex; // " " index of |basis><basis| in the flat density matrix
+
1976 
+
1977  // array of each thread's collected probability, to be summed
+
1978  extern __shared__ qreal tempReductionArray[];
+
1979 
+
1980  // figure out which density matrix prob that this thread is assigned
+
1981  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
1982  if (thisTask>=numTasks) return;
+
1983  thisBlock = thisTask / sizeHalfBlock;
+
1984  basisIndex = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
1985  densityIndex = (densityDim + 1) * basisIndex;
+
1986 
+
1987  // record the probability in the CUDA-BLOCK-wide array
+
1988  qreal prob = qureg.deviceStateVec.real[densityIndex]; // im[densityIndex] assumed ~ 0
+
1989  tempReductionArray[threadIdx.x] = prob;
+
1990 
+
1991  // sum the probs collected by this CUDA-BLOCK's threads into a per-CUDA-BLOCK array
+
1992  __syncthreads();
+
1993  if (threadIdx.x<blockDim.x/2){
+
1994  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
1995  }
+
1996 }
+
1997 
+ +
1999  Qureg qureg, int measureQubit, qreal *reducedArray
+
2000 ) {
+
2001  // ----- sizes
+
2002  long long int sizeBlock, // size of blocks
+
2003  sizeHalfBlock; // size of blocks halved
+
2004  // ----- indices
+
2005  long long int thisBlock, // current block
+
2006  index; // current index for first half block
+
2007  // ----- temp variables
+
2008  long long int thisTask; // task based approach for expose loop with small granularity
+
2009  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2010  // (good for shared memory parallelism)
2011 
-
2012  // ---------------------------------------------------------------- //
-
2013  // dimensions //
+
2012  extern __shared__ qreal tempReductionArray[];
+
2013 
2014  // ---------------------------------------------------------------- //
-
2015  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
2016  // and then the number to skip
-
2017  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
2018 
-
2019  // ---------------------------------------------------------------- //
-
2020  // find probability //
+
2015  // dimensions //
+
2016  // ---------------------------------------------------------------- //
+
2017  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
2018  // and then the number to skip
+
2019  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
2020 
2021  // ---------------------------------------------------------------- //
-
2022 
-
2023  //
-
2024  // --- task-based shared-memory parallel implementation
+
2022  // find probability //
+
2023  // ---------------------------------------------------------------- //
+
2024 
2025  //
-
2026 
-
2027  qreal *stateVecReal = qureg.deviceStateVec.real;
-
2028  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
2029 
-
2030  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2031  if (thisTask>=numTasks) return;
-
2032 
-
2033  thisBlock = thisTask / sizeHalfBlock;
-
2034  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2035  qreal realVal, imagVal;
-
2036  realVal = stateVecReal[index];
-
2037  imagVal = stateVecImag[index];
-
2038  tempReductionArray[threadIdx.x] = realVal*realVal + imagVal*imagVal;
-
2039  __syncthreads();
-
2040 
-
2041  if (threadIdx.x<blockDim.x/2){
-
2042  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2043  }
-
2044 }
-
2045 
-
2046 int getNumReductionLevels(long long int numValuesToReduce, int numReducedPerLevel){
-
2047  int levels=0;
-
2048  while (numValuesToReduce){
-
2049  numValuesToReduce = numValuesToReduce/numReducedPerLevel;
-
2050  levels++;
-
2051  }
-
2052  return levels;
-
2053 }
-
2054 
-
2055 void swapDouble(qreal **a, qreal **b){
-
2056  qreal *temp;
-
2057  temp = *a;
-
2058  *a = *b;
-
2059  *b = temp;
-
2060 }
-
2061 
- -
2063 {
-
2064  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
2065  long long int numValuesToReduce = densityDim >> 1; // half of the diagonal has measureQubit=0
-
2066 
-
2067  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2068  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2069  int firstTime = 1;
-
2070 
-
2071  while (numValuesToReduce > 1) {
-
2072 
-
2073  // need less than one CUDA-BLOCK to reduce
-
2074  if (numValuesToReduce < maxReducedPerLevel) {
-
2075  valuesPerCUDABlock = numValuesToReduce;
-
2076  numCUDABlocks = 1;
-
2077  }
-
2078  // otherwise use only full CUDA-BLOCKS
-
2079  else {
-
2080  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2081  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2082  }
-
2083 
-
2084  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2026  // --- task-based shared-memory parallel implementation
+
2027  //
+
2028 
+
2029  qreal *stateVecReal = qureg.deviceStateVec.real;
+
2030  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
2031 
+
2032  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
2033  if (thisTask>=numTasks) return;
+
2034 
+
2035  thisBlock = thisTask / sizeHalfBlock;
+
2036  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2037  qreal realVal, imagVal;
+
2038  realVal = stateVecReal[index];
+
2039  imagVal = stateVecImag[index];
+
2040  tempReductionArray[threadIdx.x] = realVal*realVal + imagVal*imagVal;
+
2041  __syncthreads();
+
2042 
+
2043  if (threadIdx.x<blockDim.x/2){
+
2044  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2045  }
+
2046 }
+
2047 
+
2048 int getNumReductionLevels(long long int numValuesToReduce, int numReducedPerLevel){
+
2049  int levels=0;
+
2050  while (numValuesToReduce){
+
2051  numValuesToReduce = numValuesToReduce/numReducedPerLevel;
+
2052  levels++;
+
2053  }
+
2054  return levels;
+
2055 }
+
2056 
+
2057 void swapDouble(qreal **a, qreal **b){
+
2058  qreal *temp;
+
2059  temp = *a;
+
2060  *a = *b;
+
2061  *b = temp;
+
2062 }
+
2063 
+ +
2065 {
+
2066  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
2067  long long int numValuesToReduce = densityDim >> 1; // half of the diagonal has measureQubit=0
+
2068 
+
2069  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2070  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2071  int firstTime = 1;
+
2072 
+
2073  while (numValuesToReduce > 1) {
+
2074 
+
2075  // need less than one CUDA-BLOCK to reduce
+
2076  if (numValuesToReduce < maxReducedPerLevel) {
+
2077  valuesPerCUDABlock = numValuesToReduce;
+
2078  numCUDABlocks = 1;
+
2079  }
+
2080  // otherwise use only full CUDA-BLOCKS
+
2081  else {
+
2082  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2083  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2084  }
2085 
-
2086  // spawn threads to sum the probs in each block
-
2087  if (firstTime) {
-
2088  densmatr_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2089  qureg, measureQubit, qureg.firstLevelReduction);
-
2090  firstTime = 0;
-
2091 
-
2092  // sum the block probs
-
2093  } else {
-
2094  cudaDeviceSynchronize();
-
2095  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2096  qureg.firstLevelReduction,
-
2097  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2098  cudaDeviceSynchronize();
- -
2100  }
-
2101 
-
2102  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2103  }
-
2104 
-
2105  qreal zeroProb;
-
2106  cudaMemcpy(&zeroProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2107  return zeroProb;
-
2108 }
-
2109 
- -
2111 {
-
2112  long long int numValuesToReduce = qureg.numAmpsPerChunk>>1;
-
2113  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2114  qreal stateProb=0;
-
2115  int firstTime=1;
-
2116  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2117 
-
2118  while(numValuesToReduce>1){
-
2119  if (numValuesToReduce<maxReducedPerLevel){
-
2120  // Need less than one CUDA block to reduce values
-
2121  valuesPerCUDABlock = numValuesToReduce;
-
2122  numCUDABlocks = 1;
-
2123  } else {
-
2124  // Use full CUDA blocks, with block size constrained by shared mem usage
-
2125  valuesPerCUDABlock = maxReducedPerLevel;
-
2126  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2127  }
-
2128  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2129 
-
2130  if (firstTime){
-
2131  statevec_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2132  qureg, measureQubit, qureg.firstLevelReduction);
-
2133  firstTime=0;
-
2134  } else {
-
2135  cudaDeviceSynchronize();
-
2136  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2137  qureg.firstLevelReduction,
-
2138  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2139  cudaDeviceSynchronize();
- -
2141  }
-
2142  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2143  }
-
2144  cudaMemcpy(&stateProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2145  return stateProb;
-
2146 }
-
2147 
-
2148 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
2149 {
-
2150  qreal outcomeProb = statevec_findProbabilityOfZero(qureg, measureQubit);
-
2151  if (outcome==1)
-
2152  outcomeProb = 1.0 - outcomeProb;
-
2153  return outcomeProb;
-
2154 }
-
2155 
-
2156 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
2157 {
-
2158  qreal outcomeProb = densmatr_findProbabilityOfZero(qureg, measureQubit);
-
2159  if (outcome==1)
-
2160  outcomeProb = 1.0 - outcomeProb;
-
2161  return outcomeProb;
-
2162 }
-
2163 
-
2164 // atomicAdd on floats/doubles isn't available on <6 CC devices, so we add it ourselves
-
2165 #if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 600
-
2166 #else
-
2167 static __inline__ __device__ double atomicAdd(double* address, double val)
-
2168 {
-
2169  unsigned long long int* address_as_ull = (unsigned long long int*) address;
-
2170  unsigned long long int old = *address_as_ull, assumed;
-
2171 
-
2172  do {
-
2173  assumed = old;
-
2174  old = atomicCAS(address_as_ull, assumed,
-
2175  __double_as_longlong(val + __longlong_as_double(assumed)));
-
2176 
-
2177  // Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN)
-
2178  } while (assumed != old);
-
2179 
-
2180  return __longlong_as_double(old);
-
2181 }
-
2182 #endif
-
2183 
- -
2185  qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits
-
2186 ) {
-
2187  // each thread handles one amplitude (all amplitudes are involved)
-
2188  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2189  if (ampInd >= qureg.numAmpsTotal) return;
-
2190 
-
2191  qreal prob = (
-
2192  qureg.deviceStateVec.real[ampInd]*qureg.deviceStateVec.real[ampInd] +
-
2193  qureg.deviceStateVec.imag[ampInd]*qureg.deviceStateVec.imag[ampInd]);
-
2194 
-
2195  // each amplitude contributes to one outcome
-
2196  long long int outcomeInd = 0;
-
2197  for (int q=0; q<numQubits; q++)
-
2198  outcomeInd += extractBit(qubits[q], ampInd) * (1LL << q);
-
2199 
-
2200  // each thread atomically writes directly to the global output.
-
2201  // this beat block-heirarchal atomic reductions in both global and shared memory!
-
2202  atomicAdd(&outcomeProbs[outcomeInd], prob);
-
2203 }
-
2204 
-
2205 void statevec_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
+
2086  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2087 
+
2088  // spawn threads to sum the probs in each block
+
2089  if (firstTime) {
+
2090  densmatr_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2091  qureg, measureQubit, qureg.firstLevelReduction);
+
2092  firstTime = 0;
+
2093 
+
2094  // sum the block probs
+
2095  } else {
+
2096  cudaDeviceSynchronize();
+
2097  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2098  qureg.firstLevelReduction,
+
2099  qureg.secondLevelReduction, valuesPerCUDABlock);
+
2100  cudaDeviceSynchronize();
+ +
2102  }
+
2103 
+
2104  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2105  }
+
2106 
+
2107  qreal zeroProb;
+
2108  cudaMemcpy(&zeroProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2109  return zeroProb;
+
2110 }
+
2111 
+ +
2113 {
+
2114  long long int numValuesToReduce = qureg.numAmpsPerChunk>>1;
+
2115  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2116  qreal stateProb=0;
+
2117  int firstTime=1;
+
2118  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2119 
+
2120  while(numValuesToReduce>1){
+
2121  if (numValuesToReduce<maxReducedPerLevel){
+
2122  // Need less than one CUDA block to reduce values
+
2123  valuesPerCUDABlock = numValuesToReduce;
+
2124  numCUDABlocks = 1;
+
2125  } else {
+
2126  // Use full CUDA blocks, with block size constrained by shared mem usage
+
2127  valuesPerCUDABlock = maxReducedPerLevel;
+
2128  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2129  }
+
2130  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2131 
+
2132  if (firstTime){
+
2133  statevec_findProbabilityOfZeroKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2134  qureg, measureQubit, qureg.firstLevelReduction);
+
2135  firstTime=0;
+
2136  } else {
+
2137  cudaDeviceSynchronize();
+
2138  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2139  qureg.firstLevelReduction,
+
2140  qureg.secondLevelReduction, valuesPerCUDABlock);
+
2141  cudaDeviceSynchronize();
+ +
2143  }
+
2144  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2145  }
+
2146  cudaMemcpy(&stateProb, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2147  return stateProb;
+
2148 }
+
2149 
+
2150 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
2151 {
+
2152  qreal outcomeProb = statevec_findProbabilityOfZero(qureg, measureQubit);
+
2153  if (outcome==1)
+
2154  outcomeProb = 1.0 - outcomeProb;
+
2155  return outcomeProb;
+
2156 }
+
2157 
+
2158 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
2159 {
+
2160  qreal outcomeProb = densmatr_findProbabilityOfZero(qureg, measureQubit);
+
2161  if (outcome==1)
+
2162  outcomeProb = 1.0 - outcomeProb;
+
2163  return outcomeProb;
+
2164 }
+
2165 
+
2166 // atomicAdd on floats/doubles isn't available on <6 CC devices, so we add it ourselves
+
2167 #if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ >= 600
+
2168 #else
+
2169 static __inline__ __device__ double atomicAdd(double* address, double val)
+
2170 {
+
2171  unsigned long long int* address_as_ull = (unsigned long long int*) address;
+
2172  unsigned long long int old = *address_as_ull, assumed;
+
2173 
+
2174  do {
+
2175  assumed = old;
+
2176  old = atomicCAS(address_as_ull, assumed,
+
2177  __double_as_longlong(val + __longlong_as_double(assumed)));
+
2178 
+
2179  // Note: uses integer comparison to avoid hang in case of NaN (since NaN != NaN)
+
2180  } while (assumed != old);
+
2181 
+
2182  return __longlong_as_double(old);
+
2183 }
+
2184 #endif
+
2185 
+ +
2187  qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits
+
2188 ) {
+
2189  // each thread handles one amplitude (all amplitudes are involved)
+
2190  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2191  if (ampInd >= qureg.numAmpsTotal) return;
+
2192 
+
2193  qreal prob = (
+
2194  qureg.deviceStateVec.real[ampInd]*qureg.deviceStateVec.real[ampInd] +
+
2195  qureg.deviceStateVec.imag[ampInd]*qureg.deviceStateVec.imag[ampInd]);
+
2196 
+
2197  // each amplitude contributes to one outcome
+
2198  long long int outcomeInd = 0;
+
2199  for (int q=0; q<numQubits; q++)
+
2200  outcomeInd += extractBit(qubits[q], ampInd) * (1LL << q);
+
2201 
+
2202  // each thread atomically writes directly to the global output.
+
2203  // this beat block-heirarchal atomic reductions in both global and shared memory!
+
2204  atomicAdd(&outcomeProbs[outcomeInd], prob);
+
2205 }
2206 
-
2207  // copy qubits to GPU memory
-
2208  int* d_qubits;
-
2209  size_t mem_qubits = numQubits * sizeof *d_qubits;
-
2210  cudaMalloc(&d_qubits, mem_qubits);
-
2211  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
2212 
-
2213  // create one thread for every amplitude
-
2214  int numThreadsPerBlock = 128;
-
2215  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
-
2216 
-
2217  // create global GPU array for outcomeProbs
-
2218  qreal* d_outcomeProbs;
-
2219  long long int numOutcomes = (1LL << numQubits);
-
2220  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
-
2221  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
-
2222  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
-
2223 
-
2224  // populate per-block subarrays
-
2225  statevec_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
-
2226  d_outcomeProbs, qureg, d_qubits, numQubits);
-
2227 
-
2228  // copy outcomeProbs from GPU memory
-
2229  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
-
2230 
-
2231  // free GPU memory
-
2232  cudaFree(d_qubits);
-
2233  cudaFree(d_outcomeProbs);
-
2234 }
-
2235 
- -
2237  qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits
-
2238 ) {
-
2239  // each thread handles one diagonal amplitude
-
2240  long long int diagInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2241  long long int numDiags = (1LL << qureg.numQubitsRepresented);
-
2242  if (diagInd >= numDiags) return;
-
2243 
-
2244  long long int flatInd = (1 + numDiags)*diagInd;
-
2245  qreal prob = qureg.deviceStateVec.real[flatInd]; // im[flatInd] assumed ~ 0
-
2246 
-
2247  // each diagonal amplitude contributes to one outcome
-
2248  long long int outcomeInd = 0;
-
2249  for (int q=0; q<numQubits; q++)
-
2250  outcomeInd += extractBit(qubits[q], diagInd) * (1LL << q);
-
2251 
-
2252  // each thread atomically writes directly to the global output.
-
2253  // this beat block-heirarchal atomic reductions in both global and shared memory!
-
2254  atomicAdd(&outcomeProbs[outcomeInd], prob);
-
2255 }
-
2256 
-
2257 void densmatr_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
+
2207 void statevec_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
+
2208 
+
2209  // copy qubits to GPU memory
+
2210  int* d_qubits;
+
2211  size_t mem_qubits = numQubits * sizeof *d_qubits;
+
2212  cudaMalloc(&d_qubits, mem_qubits);
+
2213  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
2214 
+
2215  // create one thread for every amplitude
+
2216  int numThreadsPerBlock = 128;
+
2217  int numBlocks = ceil(qureg.numAmpsPerChunk / (qreal) numThreadsPerBlock);
+
2218 
+
2219  // create global GPU array for outcomeProbs
+
2220  qreal* d_outcomeProbs;
+
2221  long long int numOutcomes = (1LL << numQubits);
+
2222  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
+
2223  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
+
2224  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
+
2225 
+
2226  // populate per-block subarrays
+
2227  statevec_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
+
2228  d_outcomeProbs, qureg, d_qubits, numQubits);
+
2229 
+
2230  // copy outcomeProbs from GPU memory
+
2231  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
+
2232 
+
2233  // free GPU memory
+
2234  cudaFree(d_qubits);
+
2235  cudaFree(d_outcomeProbs);
+
2236 }
+
2237 
+ +
2239  qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits
+
2240 ) {
+
2241  // each thread handles one diagonal amplitude
+
2242  long long int diagInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2243  long long int numDiags = (1LL << qureg.numQubitsRepresented);
+
2244  if (diagInd >= numDiags) return;
+
2245 
+
2246  long long int flatInd = (1 + numDiags)*diagInd;
+
2247  qreal prob = qureg.deviceStateVec.real[flatInd]; // im[flatInd] assumed ~ 0
+
2248 
+
2249  // each diagonal amplitude contributes to one outcome
+
2250  long long int outcomeInd = 0;
+
2251  for (int q=0; q<numQubits; q++)
+
2252  outcomeInd += extractBit(qubits[q], diagInd) * (1LL << q);
+
2253 
+
2254  // each thread atomically writes directly to the global output.
+
2255  // this beat block-heirarchal atomic reductions in both global and shared memory!
+
2256  atomicAdd(&outcomeProbs[outcomeInd], prob);
+
2257 }
2258 
-
2259  // copy qubits to GPU memory
-
2260  int* d_qubits;
-
2261  size_t mem_qubits = numQubits * sizeof *d_qubits;
-
2262  cudaMalloc(&d_qubits, mem_qubits);
-
2263  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
2264 
-
2265  // create global array, with per-block subarrays
-
2266  int numThreadsPerBlock = 128;
-
2267  int numDiags = (1LL << qureg.numQubitsRepresented);
-
2268  int numBlocks = ceil(numDiags / (qreal) numThreadsPerBlock);
-
2269 
-
2270  // create global GPU array for outcomeProbs
-
2271  qreal* d_outcomeProbs;
-
2272  long long int numOutcomes = (1LL << numQubits);
-
2273  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
-
2274  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
-
2275  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
-
2276 
-
2277  // populate per-block subarrays
-
2278  densmatr_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
-
2279  d_outcomeProbs, qureg, d_qubits, numQubits);
-
2280 
-
2281  // copy outcomeProbs from GPU memory
-
2282  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
-
2283 
-
2284  // free GPU memory
-
2285  cudaFree(d_qubits);
-
2286  cudaFree(d_outcomeProbs);
-
2287 }
-
2288 
- -
2291  Qureg a, Qureg b, long long int numTermsToSum, qreal* reducedArray
-
2292 ) {
-
2293  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2294  if (index >= numTermsToSum) return;
-
2295 
-
2296  // Re{ conj(a) b } = Re{ (aRe - i aIm)(bRe + i bIm) } = aRe bRe + aIm bIm
-
2297  qreal prod = (
-
2298  a.deviceStateVec.real[index]*b.deviceStateVec.real[index]
-
2299  + a.deviceStateVec.imag[index]*b.deviceStateVec.imag[index]);
-
2300 
-
2301  // array of each thread's collected sum term, to be summed
-
2302  extern __shared__ qreal tempReductionArray[];
-
2303  tempReductionArray[threadIdx.x] = prod;
-
2304  __syncthreads();
-
2305 
-
2306  // every second thread reduces
-
2307  if (threadIdx.x<blockDim.x/2)
-
2308  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2309 }
-
2310 
- -
2312 
-
2313  // we're summing the square of every term in the density matrix
-
2314  long long int numValuesToReduce = a.numAmpsTotal;
-
2315 
-
2316  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2317  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2318  int firstTime = 1;
-
2319 
-
2320  while (numValuesToReduce > 1) {
-
2321 
-
2322  // need less than one CUDA-BLOCK to reduce
-
2323  if (numValuesToReduce < maxReducedPerLevel) {
-
2324  valuesPerCUDABlock = numValuesToReduce;
-
2325  numCUDABlocks = 1;
-
2326  }
-
2327  // otherwise use only full CUDA-BLOCKS
-
2328  else {
-
2329  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2330  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2331  }
-
2332  // dictates size of reduction array
-
2333  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2334 
-
2335  // spawn threads to sum the terms in each block
-
2336  // arbitrarily store the reduction in the b qureg's array
-
2337  if (firstTime) {
-
2338  densmatr_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2339  a, b, a.numAmpsTotal, b.firstLevelReduction);
-
2340  firstTime = 0;
-
2341  }
-
2342  // sum the block terms
-
2343  else {
-
2344  cudaDeviceSynchronize();
-
2345  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2347  b.secondLevelReduction, valuesPerCUDABlock);
-
2348  cudaDeviceSynchronize();
- -
2350  }
-
2351 
-
2352  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2353  }
-
2354 
-
2355  qreal innerprod;
-
2356  cudaMemcpy(&innerprod, b.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2357  return innerprod;
-
2358 }
-
2359 
- -
2362  int getRealComp,
-
2363  qreal* vecReal1, qreal* vecImag1, qreal* vecReal2, qreal* vecImag2,
-
2364  long long int numTermsToSum, qreal* reducedArray)
-
2365 {
-
2366  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2367  if (index >= numTermsToSum) return;
-
2368 
-
2369  // choose whether to calculate the real or imaginary term of the inner product
-
2370  qreal innerProdTerm;
-
2371  if (getRealComp)
-
2372  innerProdTerm = vecReal1[index]*vecReal2[index] + vecImag1[index]*vecImag2[index];
-
2373  else
-
2374  innerProdTerm = vecReal1[index]*vecImag2[index] - vecImag1[index]*vecReal2[index];
-
2375 
-
2376  // array of each thread's collected sum term, to be summed
-
2377  extern __shared__ qreal tempReductionArray[];
-
2378  tempReductionArray[threadIdx.x] = innerProdTerm;
-
2379  __syncthreads();
-
2380 
-
2381  // every second thread reduces
-
2382  if (threadIdx.x<blockDim.x/2)
-
2383  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2384 }
-
2385 
- -
2392 
-
2393  qreal innerProdReal, innerProdImag;
+
2259 void densmatr_calcProbOfAllOutcomes(qreal* outcomeProbs, Qureg qureg, int* qubits, int numQubits) {
+
2260 
+
2261  // copy qubits to GPU memory
+
2262  int* d_qubits;
+
2263  size_t mem_qubits = numQubits * sizeof *d_qubits;
+
2264  cudaMalloc(&d_qubits, mem_qubits);
+
2265  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
2266 
+
2267  // create global array, with per-block subarrays
+
2268  int numThreadsPerBlock = 128;
+
2269  int numDiags = (1LL << qureg.numQubitsRepresented);
+
2270  int numBlocks = ceil(numDiags / (qreal) numThreadsPerBlock);
+
2271 
+
2272  // create global GPU array for outcomeProbs
+
2273  qreal* d_outcomeProbs;
+
2274  long long int numOutcomes = (1LL << numQubits);
+
2275  size_t mem_outcomeProbs = numOutcomes * sizeof *d_outcomeProbs;
+
2276  cudaMalloc(&d_outcomeProbs, mem_outcomeProbs);
+
2277  cudaMemset(d_outcomeProbs, 0, mem_outcomeProbs);
+
2278 
+
2279  // populate per-block subarrays
+
2280  densmatr_calcProbOfAllOutcomesKernel<<<numBlocks, numThreadsPerBlock>>>(
+
2281  d_outcomeProbs, qureg, d_qubits, numQubits);
+
2282 
+
2283  // copy outcomeProbs from GPU memory
+
2284  cudaMemcpy(outcomeProbs, d_outcomeProbs, mem_outcomeProbs, cudaMemcpyDeviceToHost);
+
2285 
+
2286  // free GPU memory
+
2287  cudaFree(d_qubits);
+
2288  cudaFree(d_outcomeProbs);
+
2289 }
+
2290 
+ +
2293  Qureg a, Qureg b, long long int numTermsToSum, qreal* reducedArray
+
2294 ) {
+
2295  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2296  if (index >= numTermsToSum) return;
+
2297 
+
2298  // Re{ conj(a) b } = Re{ (aRe - i aIm)(bRe + i bIm) } = aRe bRe + aIm bIm
+
2299  qreal prod = (
+
2300  a.deviceStateVec.real[index]*b.deviceStateVec.real[index]
+
2301  + a.deviceStateVec.imag[index]*b.deviceStateVec.imag[index]);
+
2302 
+
2303  // array of each thread's collected sum term, to be summed
+
2304  extern __shared__ qreal tempReductionArray[];
+
2305  tempReductionArray[threadIdx.x] = prod;
+
2306  __syncthreads();
+
2307 
+
2308  // every second thread reduces
+
2309  if (threadIdx.x<blockDim.x/2)
+
2310  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2311 }
+
2312 
+ +
2314 
+
2315  // we're summing the square of every term in the density matrix
+
2316  long long int numValuesToReduce = a.numAmpsTotal;
+
2317 
+
2318  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2319  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2320  int firstTime = 1;
+
2321 
+
2322  while (numValuesToReduce > 1) {
+
2323 
+
2324  // need less than one CUDA-BLOCK to reduce
+
2325  if (numValuesToReduce < maxReducedPerLevel) {
+
2326  valuesPerCUDABlock = numValuesToReduce;
+
2327  numCUDABlocks = 1;
+
2328  }
+
2329  // otherwise use only full CUDA-BLOCKS
+
2330  else {
+
2331  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2332  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2333  }
+
2334  // dictates size of reduction array
+
2335  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2336 
+
2337  // spawn threads to sum the terms in each block
+
2338  // arbitrarily store the reduction in the b qureg's array
+
2339  if (firstTime) {
+
2340  densmatr_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2341  a, b, a.numAmpsTotal, b.firstLevelReduction);
+
2342  firstTime = 0;
+
2343  }
+
2344  // sum the block terms
+
2345  else {
+
2346  cudaDeviceSynchronize();
+
2347  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+ +
2349  b.secondLevelReduction, valuesPerCUDABlock);
+
2350  cudaDeviceSynchronize();
+ +
2352  }
+
2353 
+
2354  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2355  }
+
2356 
+
2357  qreal innerprod;
+
2358  cudaMemcpy(&innerprod, b.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2359  return innerprod;
+
2360 }
+
2361 
+ +
2364  int getRealComp,
+
2365  qreal* vecReal1, qreal* vecImag1, qreal* vecReal2, qreal* vecImag2,
+
2366  long long int numTermsToSum, qreal* reducedArray)
+
2367 {
+
2368  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2369  if (index >= numTermsToSum) return;
+
2370 
+
2371  // choose whether to calculate the real or imaginary term of the inner product
+
2372  qreal innerProdTerm;
+
2373  if (getRealComp)
+
2374  innerProdTerm = vecReal1[index]*vecReal2[index] + vecImag1[index]*vecImag2[index];
+
2375  else
+
2376  innerProdTerm = vecReal1[index]*vecImag2[index] - vecImag1[index]*vecReal2[index];
+
2377 
+
2378  // array of each thread's collected sum term, to be summed
+
2379  extern __shared__ qreal tempReductionArray[];
+
2380  tempReductionArray[threadIdx.x] = innerProdTerm;
+
2381  __syncthreads();
+
2382 
+
2383  // every second thread reduces
+
2384  if (threadIdx.x<blockDim.x/2)
+
2385  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2386 }
+
2387 
+
2394 
-
2395  int getRealComp;
-
2396  long long int numValuesToReduce;
-
2397  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2398  int maxReducedPerLevel;
-
2399  int firstTime;
-
2400 
-
2401  // compute real component of inner product
-
2402  getRealComp = 1;
-
2403  numValuesToReduce = bra.numAmpsPerChunk;
-
2404  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2405  firstTime = 1;
-
2406  while (numValuesToReduce > 1) {
-
2407  if (numValuesToReduce < maxReducedPerLevel) {
-
2408  valuesPerCUDABlock = numValuesToReduce;
-
2409  numCUDABlocks = 1;
-
2410  }
-
2411  else {
-
2412  valuesPerCUDABlock = maxReducedPerLevel;
-
2413  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2414  }
-
2415  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2416  if (firstTime) {
-
2417  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2418  getRealComp,
-
2419  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2420  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2421  numValuesToReduce,
-
2422  bra.firstLevelReduction);
-
2423  firstTime = 0;
-
2424  } else {
-
2425  cudaDeviceSynchronize();
-
2426  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2427  bra.firstLevelReduction,
-
2428  bra.secondLevelReduction, valuesPerCUDABlock);
-
2429  cudaDeviceSynchronize();
- -
2431  }
-
2432  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2433  }
-
2434  cudaMemcpy(&innerProdReal, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2435 
-
2436  // compute imag component of inner product
-
2437  getRealComp = 0;
-
2438  numValuesToReduce = bra.numAmpsPerChunk;
-
2439  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2440  firstTime = 1;
-
2441  while (numValuesToReduce > 1) {
-
2442  if (numValuesToReduce < maxReducedPerLevel) {
-
2443  valuesPerCUDABlock = numValuesToReduce;
-
2444  numCUDABlocks = 1;
-
2445  }
-
2446  else {
-
2447  valuesPerCUDABlock = maxReducedPerLevel;
-
2448  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2449  }
-
2450  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2451  if (firstTime) {
-
2452  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2453  getRealComp,
-
2454  bra.deviceStateVec.real, bra.deviceStateVec.imag,
-
2455  ket.deviceStateVec.real, ket.deviceStateVec.imag,
-
2456  numValuesToReduce,
-
2457  bra.firstLevelReduction);
-
2458  firstTime = 0;
-
2459  } else {
-
2460  cudaDeviceSynchronize();
-
2461  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2462  bra.firstLevelReduction,
-
2463  bra.secondLevelReduction, valuesPerCUDABlock);
-
2464  cudaDeviceSynchronize();
- -
2466  }
-
2467  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2468  }
-
2469  cudaMemcpy(&innerProdImag, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2470 
-
2471  // return complex
-
2472  Complex innerProd;
-
2473  innerProd.real = innerProdReal;
-
2474  innerProd.imag = innerProdImag;
-
2475  return innerProd;
-
2476 }
-
2477 
-
2479 __global__ void densmatr_calcFidelityKernel(Qureg dens, Qureg vec, long long int dim, qreal* reducedArray) {
-
2480 
-
2481  // figure out which density matrix row to consider
-
2482  long long int col;
-
2483  long long int row = blockIdx.x*blockDim.x + threadIdx.x;
-
2484  if (row >= dim) return;
-
2485 
-
2486  qreal* densReal = dens.deviceStateVec.real;
-
2487  qreal* densImag = dens.deviceStateVec.imag;
-
2488  qreal* vecReal = vec.deviceStateVec.real;
-
2489  qreal* vecImag = vec.deviceStateVec.imag;
-
2490 
-
2491  // compute the row-th element of the product dens*vec
-
2492  qreal prodReal = 0;
-
2493  qreal prodImag = 0;
-
2494  for (col=0LL; col < dim; col++) {
-
2495  qreal densElemReal = densReal[dim*col + row];
-
2496  qreal densElemImag = densImag[dim*col + row];
-
2497 
-
2498  prodReal += densElemReal*vecReal[col] - densElemImag*vecImag[col];
-
2499  prodImag += densElemReal*vecImag[col] + densElemImag*vecReal[col];
-
2500  }
-
2501 
-
2502  // multiply with row-th elem of (vec^*)
-
2503  qreal termReal = prodImag*vecImag[row] + prodReal*vecReal[row];
-
2504 
-
2505  // imag of every term should be zero, because each is a valid fidelity calc of an eigenstate
-
2506  //qreal termImag = prodImag*vecReal[row] - prodReal*vecImag[row];
-
2507 
-
2508  extern __shared__ qreal tempReductionArray[];
-
2509  tempReductionArray[threadIdx.x] = termReal;
-
2510  __syncthreads();
-
2511 
-
2512  // every second thread reduces
-
2513  if (threadIdx.x<blockDim.x/2)
-
2514  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2515 }
-
2516 
- -
2518 
-
2519  // we're summing the square of every term in the density matrix
-
2520  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
2521  long long int numValuesToReduce = densityDim;
-
2522 
-
2523  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2524  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2525  int firstTime = 1;
-
2526 
-
2527  while (numValuesToReduce > 1) {
-
2528 
-
2529  // need less than one CUDA-BLOCK to reduce
-
2530  if (numValuesToReduce < maxReducedPerLevel) {
-
2531  valuesPerCUDABlock = numValuesToReduce;
-
2532  numCUDABlocks = 1;
-
2533  }
-
2534  // otherwise use only full CUDA-BLOCKS
-
2535  else {
-
2536  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2537  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2538  }
-
2539  // dictates size of reduction array
-
2540  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2541 
-
2542  // spawn threads to sum the probs in each block
-
2543  // store the reduction in the pureState array
-
2544  if (firstTime) {
-
2545  densmatr_calcFidelityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2546  qureg, pureState, densityDim, pureState.firstLevelReduction);
-
2547  firstTime = 0;
-
2548 
-
2549  // sum the block probs
-
2550  } else {
-
2551  cudaDeviceSynchronize();
-
2552  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2553  pureState.firstLevelReduction,
-
2554  pureState.secondLevelReduction, valuesPerCUDABlock);
-
2555  cudaDeviceSynchronize();
-
2556  swapDouble(&(pureState.firstLevelReduction), &(pureState.secondLevelReduction));
-
2557  }
-
2558 
-
2559  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2560  }
-
2561 
-
2562  qreal fidelity;
-
2563  cudaMemcpy(&fidelity, pureState.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2564  return fidelity;
-
2565 }
-
2566 
- -
2568  qreal* aRe, qreal* aIm, qreal* bRe, qreal* bIm,
-
2569  long long int numAmpsToSum, qreal *reducedArray
-
2570 ) {
-
2571  // figure out which density matrix term this thread is assigned
-
2572  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2573  if (index >= numAmpsToSum) return;
-
2574 
-
2575  // compute this thread's sum term
-
2576  qreal difRe = aRe[index] - bRe[index];
-
2577  qreal difIm = aIm[index] - bIm[index];
-
2578  qreal term = difRe*difRe + difIm*difIm;
-
2579 
-
2580  // array of each thread's collected term, to be summed
-
2581  extern __shared__ qreal tempReductionArray[];
-
2582  tempReductionArray[threadIdx.x] = term;
-
2583  __syncthreads();
-
2584 
-
2585  // every second thread reduces
-
2586  if (threadIdx.x<blockDim.x/2)
-
2587  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2588 }
-
2589 
-
2590 /* computes sqrt(Tr( (a-b) conjTrans(a-b) ) = sqrt( sum of abs vals of (a-b)) */
- -
2592 
-
2593  // we're summing the square of every term in (a-b)
-
2594  long long int numValuesToReduce = a.numAmpsPerChunk;
-
2595 
-
2596  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2597  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2598  int firstTime = 1;
-
2599 
-
2600  while (numValuesToReduce > 1) {
-
2601 
-
2602  // need less than one CUDA-BLOCK to reduce
-
2603  if (numValuesToReduce < maxReducedPerLevel) {
-
2604  valuesPerCUDABlock = numValuesToReduce;
-
2605  numCUDABlocks = 1;
-
2606  }
-
2607  // otherwise use only full CUDA-BLOCKS
-
2608  else {
-
2609  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2610  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2611  }
-
2612  // dictates size of reduction array
-
2613  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2614 
-
2615  // spawn threads to sum the probs in each block (store reduction temp values in a's reduction array)
-
2616  if (firstTime) {
-
2617  densmatr_calcHilbertSchmidtDistanceSquaredKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2618  a.deviceStateVec.real, a.deviceStateVec.imag,
-
2619  b.deviceStateVec.real, b.deviceStateVec.imag,
-
2620  numValuesToReduce, a.firstLevelReduction);
-
2621  firstTime = 0;
-
2622 
-
2623  // sum the block probs
-
2624  } else {
-
2625  cudaDeviceSynchronize();
-
2626  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
- -
2628  a.secondLevelReduction, valuesPerCUDABlock);
-
2629  cudaDeviceSynchronize();
- -
2631  }
-
2632 
-
2633  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2634  }
-
2635 
-
2636  qreal trace;
-
2637  cudaMemcpy(&trace, a.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2638 
-
2639  qreal sqrtTrace = sqrt(trace);
-
2640  return sqrtTrace;
-
2641 }
-
2642 
-
2643 __global__ void densmatr_calcPurityKernel(qreal* vecReal, qreal* vecImag, long long int numAmpsToSum, qreal *reducedArray) {
-
2644 
-
2645  // figure out which density matrix term this thread is assigned
-
2646  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
2647  if (index >= numAmpsToSum) return;
-
2648 
-
2649  qreal term = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+
2395  qreal innerProdReal, innerProdImag;
+
2396 
+
2397  int getRealComp;
+
2398  long long int numValuesToReduce;
+
2399  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2400  int maxReducedPerLevel;
+
2401  int firstTime;
+
2402 
+
2403  // compute real component of inner product
+
2404  getRealComp = 1;
+
2405  numValuesToReduce = bra.numAmpsPerChunk;
+
2406  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2407  firstTime = 1;
+
2408  while (numValuesToReduce > 1) {
+
2409  if (numValuesToReduce < maxReducedPerLevel) {
+
2410  valuesPerCUDABlock = numValuesToReduce;
+
2411  numCUDABlocks = 1;
+
2412  }
+
2413  else {
+
2414  valuesPerCUDABlock = maxReducedPerLevel;
+
2415  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2416  }
+
2417  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2418  if (firstTime) {
+
2419  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2420  getRealComp,
+
2421  bra.deviceStateVec.real, bra.deviceStateVec.imag,
+
2422  ket.deviceStateVec.real, ket.deviceStateVec.imag,
+
2423  numValuesToReduce,
+
2424  bra.firstLevelReduction);
+
2425  firstTime = 0;
+
2426  } else {
+
2427  cudaDeviceSynchronize();
+
2428  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2429  bra.firstLevelReduction,
+
2430  bra.secondLevelReduction, valuesPerCUDABlock);
+
2431  cudaDeviceSynchronize();
+ +
2433  }
+
2434  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2435  }
+
2436  cudaMemcpy(&innerProdReal, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2437 
+
2438  // compute imag component of inner product
+
2439  getRealComp = 0;
+
2440  numValuesToReduce = bra.numAmpsPerChunk;
+
2441  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2442  firstTime = 1;
+
2443  while (numValuesToReduce > 1) {
+
2444  if (numValuesToReduce < maxReducedPerLevel) {
+
2445  valuesPerCUDABlock = numValuesToReduce;
+
2446  numCUDABlocks = 1;
+
2447  }
+
2448  else {
+
2449  valuesPerCUDABlock = maxReducedPerLevel;
+
2450  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2451  }
+
2452  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2453  if (firstTime) {
+
2454  statevec_calcInnerProductKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2455  getRealComp,
+
2456  bra.deviceStateVec.real, bra.deviceStateVec.imag,
+
2457  ket.deviceStateVec.real, ket.deviceStateVec.imag,
+
2458  numValuesToReduce,
+
2459  bra.firstLevelReduction);
+
2460  firstTime = 0;
+
2461  } else {
+
2462  cudaDeviceSynchronize();
+
2463  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2464  bra.firstLevelReduction,
+
2465  bra.secondLevelReduction, valuesPerCUDABlock);
+
2466  cudaDeviceSynchronize();
+ +
2468  }
+
2469  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2470  }
+
2471  cudaMemcpy(&innerProdImag, bra.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2472 
+
2473  // return complex
+
2474  Complex innerProd;
+
2475  innerProd.real = innerProdReal;
+
2476  innerProd.imag = innerProdImag;
+
2477  return innerProd;
+
2478 }
+
2479 
+
2481 __global__ void densmatr_calcFidelityKernel(Qureg dens, Qureg vec, long long int dim, qreal* reducedArray) {
+
2482 
+
2483  // figure out which density matrix row to consider
+
2484  long long int col;
+
2485  long long int row = blockIdx.x*blockDim.x + threadIdx.x;
+
2486  if (row >= dim) return;
+
2487 
+
2488  qreal* densReal = dens.deviceStateVec.real;
+
2489  qreal* densImag = dens.deviceStateVec.imag;
+
2490  qreal* vecReal = vec.deviceStateVec.real;
+
2491  qreal* vecImag = vec.deviceStateVec.imag;
+
2492 
+
2493  // compute the row-th element of the product dens*vec
+
2494  qreal prodReal = 0;
+
2495  qreal prodImag = 0;
+
2496  for (col=0LL; col < dim; col++) {
+
2497  qreal densElemReal = densReal[dim*col + row];
+
2498  qreal densElemImag = densImag[dim*col + row];
+
2499 
+
2500  prodReal += densElemReal*vecReal[col] - densElemImag*vecImag[col];
+
2501  prodImag += densElemReal*vecImag[col] + densElemImag*vecReal[col];
+
2502  }
+
2503 
+
2504  // multiply with row-th elem of (vec^*)
+
2505  qreal termReal = prodImag*vecImag[row] + prodReal*vecReal[row];
+
2506 
+
2507  // imag of every term should be zero, because each is a valid fidelity calc of an eigenstate
+
2508  //qreal termImag = prodImag*vecReal[row] - prodReal*vecImag[row];
+
2509 
+
2510  extern __shared__ qreal tempReductionArray[];
+
2511  tempReductionArray[threadIdx.x] = termReal;
+
2512  __syncthreads();
+
2513 
+
2514  // every second thread reduces
+
2515  if (threadIdx.x<blockDim.x/2)
+
2516  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2517 }
+
2518 
+ +
2520 
+
2521  // we're summing the square of every term in the density matrix
+
2522  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
2523  long long int numValuesToReduce = densityDim;
+
2524 
+
2525  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2526  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2527  int firstTime = 1;
+
2528 
+
2529  while (numValuesToReduce > 1) {
+
2530 
+
2531  // need less than one CUDA-BLOCK to reduce
+
2532  if (numValuesToReduce < maxReducedPerLevel) {
+
2533  valuesPerCUDABlock = numValuesToReduce;
+
2534  numCUDABlocks = 1;
+
2535  }
+
2536  // otherwise use only full CUDA-BLOCKS
+
2537  else {
+
2538  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2539  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2540  }
+
2541  // dictates size of reduction array
+
2542  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2543 
+
2544  // spawn threads to sum the probs in each block
+
2545  // store the reduction in the pureState array
+
2546  if (firstTime) {
+
2547  densmatr_calcFidelityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2548  qureg, pureState, densityDim, pureState.firstLevelReduction);
+
2549  firstTime = 0;
+
2550 
+
2551  // sum the block probs
+
2552  } else {
+
2553  cudaDeviceSynchronize();
+
2554  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2555  pureState.firstLevelReduction,
+
2556  pureState.secondLevelReduction, valuesPerCUDABlock);
+
2557  cudaDeviceSynchronize();
+
2558  swapDouble(&(pureState.firstLevelReduction), &(pureState.secondLevelReduction));
+
2559  }
+
2560 
+
2561  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2562  }
+
2563 
+
2564  qreal fidelity;
+
2565  cudaMemcpy(&fidelity, pureState.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2566  return fidelity;
+
2567 }
+
2568 
+ +
2570  qreal* aRe, qreal* aIm, qreal* bRe, qreal* bIm,
+
2571  long long int numAmpsToSum, qreal *reducedArray
+
2572 ) {
+
2573  // figure out which density matrix term this thread is assigned
+
2574  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2575  if (index >= numAmpsToSum) return;
+
2576 
+
2577  // compute this thread's sum term
+
2578  qreal difRe = aRe[index] - bRe[index];
+
2579  qreal difIm = aIm[index] - bIm[index];
+
2580  qreal term = difRe*difRe + difIm*difIm;
+
2581 
+
2582  // array of each thread's collected term, to be summed
+
2583  extern __shared__ qreal tempReductionArray[];
+
2584  tempReductionArray[threadIdx.x] = term;
+
2585  __syncthreads();
+
2586 
+
2587  // every second thread reduces
+
2588  if (threadIdx.x<blockDim.x/2)
+
2589  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2590 }
+
2591 
+
2592 /* computes sqrt(Tr( (a-b) conjTrans(a-b) ) = sqrt( sum of abs vals of (a-b)) */
+ +
2594 
+
2595  // we're summing the square of every term in (a-b)
+
2596  long long int numValuesToReduce = a.numAmpsPerChunk;
+
2597 
+
2598  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2599  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2600  int firstTime = 1;
+
2601 
+
2602  while (numValuesToReduce > 1) {
+
2603 
+
2604  // need less than one CUDA-BLOCK to reduce
+
2605  if (numValuesToReduce < maxReducedPerLevel) {
+
2606  valuesPerCUDABlock = numValuesToReduce;
+
2607  numCUDABlocks = 1;
+
2608  }
+
2609  // otherwise use only full CUDA-BLOCKS
+
2610  else {
+
2611  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2612  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2613  }
+
2614  // dictates size of reduction array
+
2615  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2616 
+
2617  // spawn threads to sum the probs in each block (store reduction temp values in a's reduction array)
+
2618  if (firstTime) {
+
2619  densmatr_calcHilbertSchmidtDistanceSquaredKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2620  a.deviceStateVec.real, a.deviceStateVec.imag,
+
2621  b.deviceStateVec.real, b.deviceStateVec.imag,
+
2622  numValuesToReduce, a.firstLevelReduction);
+
2623  firstTime = 0;
+
2624 
+
2625  // sum the block probs
+
2626  } else {
+
2627  cudaDeviceSynchronize();
+
2628  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+ +
2630  a.secondLevelReduction, valuesPerCUDABlock);
+
2631  cudaDeviceSynchronize();
+ +
2633  }
+
2634 
+
2635  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2636  }
+
2637 
+
2638  qreal trace;
+
2639  cudaMemcpy(&trace, a.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2640 
+
2641  qreal sqrtTrace = sqrt(trace);
+
2642  return sqrtTrace;
+
2643 }
+
2644 
+
2645 __global__ void densmatr_calcPurityKernel(qreal* vecReal, qreal* vecImag, long long int numAmpsToSum, qreal *reducedArray) {
+
2646 
+
2647  // figure out which density matrix term this thread is assigned
+
2648  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
2649  if (index >= numAmpsToSum) return;
2650 
-
2651  // array of each thread's collected probability, to be summed
-
2652  extern __shared__ qreal tempReductionArray[];
-
2653  tempReductionArray[threadIdx.x] = term;
-
2654  __syncthreads();
-
2655 
-
2656  // every second thread reduces
-
2657  if (threadIdx.x<blockDim.x/2)
-
2658  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
2659 }
-
2660 
- -
2663 
-
2664  // we're summing the square of every term in the density matrix
-
2665  long long int numValuesToReduce = qureg.numAmpsPerChunk;
-
2666 
-
2667  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
2668  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
2669  int firstTime = 1;
-
2670 
-
2671  while (numValuesToReduce > 1) {
-
2672 
-
2673  // need less than one CUDA-BLOCK to reduce
-
2674  if (numValuesToReduce < maxReducedPerLevel) {
-
2675  valuesPerCUDABlock = numValuesToReduce;
-
2676  numCUDABlocks = 1;
-
2677  }
-
2678  // otherwise use only full CUDA-BLOCKS
-
2679  else {
-
2680  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
-
2681  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
2682  }
-
2683  // dictates size of reduction array
-
2684  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
2685 
-
2686  // spawn threads to sum the probs in each block
-
2687  if (firstTime) {
-
2688  densmatr_calcPurityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
2689  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
2690  numValuesToReduce, qureg.firstLevelReduction);
-
2691  firstTime = 0;
-
2692 
-
2693  // sum the block probs
-
2694  } else {
-
2695  cudaDeviceSynchronize();
-
2696  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
2697  qureg.firstLevelReduction,
-
2698  qureg.secondLevelReduction, valuesPerCUDABlock);
-
2699  cudaDeviceSynchronize();
- -
2701  }
-
2702 
-
2703  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
2704  }
-
2705 
-
2706  qreal traceDensSquared;
-
2707  cudaMemcpy(&traceDensSquared, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
2708  return traceDensSquared;
-
2709 }
-
2710 
-
2711 __global__ void statevec_collapseToKnownProbOutcomeKernel(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
-
2712 {
-
2713  // ----- sizes
-
2714  long long int sizeBlock, // size of blocks
-
2715  sizeHalfBlock; // size of blocks halved
-
2716  // ----- indices
-
2717  long long int thisBlock, // current block
-
2718  index; // current index for first half block
-
2719  // ----- measured probability
-
2720  qreal renorm; // probability (returned) value
-
2721  // ----- temp variables
-
2722  long long int thisTask; // task based approach for expose loop with small granularity
-
2723  // (good for shared memory parallelism)
-
2724  long long int numTasks=qureg.numAmpsPerChunk>>1;
-
2725 
-
2726  // ---------------------------------------------------------------- //
-
2727  // dimensions //
+
2651  qreal term = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+
2652 
+
2653  // array of each thread's collected probability, to be summed
+
2654  extern __shared__ qreal tempReductionArray[];
+
2655  tempReductionArray[threadIdx.x] = term;
+
2656  __syncthreads();
+
2657 
+
2658  // every second thread reduces
+
2659  if (threadIdx.x<blockDim.x/2)
+
2660  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
2661 }
+
2662 
+ +
2665 
+
2666  // we're summing the square of every term in the density matrix
+
2667  long long int numValuesToReduce = qureg.numAmpsPerChunk;
+
2668 
+
2669  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
2670  int maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
2671  int firstTime = 1;
+
2672 
+
2673  while (numValuesToReduce > 1) {
+
2674 
+
2675  // need less than one CUDA-BLOCK to reduce
+
2676  if (numValuesToReduce < maxReducedPerLevel) {
+
2677  valuesPerCUDABlock = numValuesToReduce;
+
2678  numCUDABlocks = 1;
+
2679  }
+
2680  // otherwise use only full CUDA-BLOCKS
+
2681  else {
+
2682  valuesPerCUDABlock = maxReducedPerLevel; // constrained by shared memory
+
2683  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
2684  }
+
2685  // dictates size of reduction array
+
2686  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
2687 
+
2688  // spawn threads to sum the probs in each block
+
2689  if (firstTime) {
+
2690  densmatr_calcPurityKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
2691  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
2692  numValuesToReduce, qureg.firstLevelReduction);
+
2693  firstTime = 0;
+
2694 
+
2695  // sum the block probs
+
2696  } else {
+
2697  cudaDeviceSynchronize();
+
2698  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
2699  qureg.firstLevelReduction,
+
2700  qureg.secondLevelReduction, valuesPerCUDABlock);
+
2701  cudaDeviceSynchronize();
+ +
2703  }
+
2704 
+
2705  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
2706  }
+
2707 
+
2708  qreal traceDensSquared;
+
2709  cudaMemcpy(&traceDensSquared, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
2710  return traceDensSquared;
+
2711 }
+
2712 
+
2713 __global__ void statevec_collapseToKnownProbOutcomeKernel(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
+
2714 {
+
2715  // ----- sizes
+
2716  long long int sizeBlock, // size of blocks
+
2717  sizeHalfBlock; // size of blocks halved
+
2718  // ----- indices
+
2719  long long int thisBlock, // current block
+
2720  index; // current index for first half block
+
2721  // ----- measured probability
+
2722  qreal renorm; // probability (returned) value
+
2723  // ----- temp variables
+
2724  long long int thisTask; // task based approach for expose loop with small granularity
+
2725  // (good for shared memory parallelism)
+
2726  long long int numTasks=qureg.numAmpsPerChunk>>1;
+
2727 
2728  // ---------------------------------------------------------------- //
-
2729  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
-
2730  // and then the number to skip
-
2731  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
-
2732 
-
2733  // ---------------------------------------------------------------- //
-
2734  // find probability //
+
2729  // dimensions //
+
2730  // ---------------------------------------------------------------- //
+
2731  sizeHalfBlock = 1LL << (measureQubit); // number of state vector elements to sum,
+
2732  // and then the number to skip
+
2733  sizeBlock = 2LL * sizeHalfBlock; // size of blocks (pairs of measure and skip entries)
+
2734 
2735  // ---------------------------------------------------------------- //
-
2736 
-
2737  //
-
2738  // --- task-based shared-memory parallel implementation
+
2736  // find probability //
+
2737  // ---------------------------------------------------------------- //
+
2738 
2739  //
-
2740  renorm=1/sqrt(totalProbability);
-
2741  qreal *stateVecReal = qureg.deviceStateVec.real;
-
2742  qreal *stateVecImag = qureg.deviceStateVec.imag;
-
2743 
-
2744  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
2745  if (thisTask>=numTasks) return;
-
2746  thisBlock = thisTask / sizeHalfBlock;
-
2747  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
-
2748 
-
2749  if (outcome==0){
-
2750  stateVecReal[index]=stateVecReal[index]*renorm;
-
2751  stateVecImag[index]=stateVecImag[index]*renorm;
-
2752 
-
2753  stateVecReal[index+sizeHalfBlock]=0;
-
2754  stateVecImag[index+sizeHalfBlock]=0;
-
2755  } else if (outcome==1){
-
2756  stateVecReal[index]=0;
-
2757  stateVecImag[index]=0;
-
2758 
-
2759  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
-
2760  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
-
2761  }
-
2762 }
-
2763 
-
2764 /*
-
2765  * outcomeProb must accurately be the probability of that qubit outcome in the state-vector, or
-
2766  * else the state-vector will lose normalisation
-
2767  */
-
2768 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
2769 {
-
2770  int threadsPerCUDABlock, CUDABlocks;
-
2771  threadsPerCUDABlock = 128;
-
2772  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
-
2773  statevec_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, measureQubit, outcome, outcomeProb);
-
2774 }
-
2775 
- -
2778  qreal outcomeProb, qreal* vecReal, qreal *vecImag, long long int numBasesToVisit,
-
2779  long long int part1, long long int part2, long long int part3,
-
2780  long long int rowBit, long long int colBit, long long int desired, long long int undesired)
-
2781 {
-
2782  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2783  if (scanInd >= numBasesToVisit) return;
-
2784 
-
2785  long long int base = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2740  // --- task-based shared-memory parallel implementation
+
2741  //
+
2742  renorm=1/sqrt(totalProbability);
+
2743  qreal *stateVecReal = qureg.deviceStateVec.real;
+
2744  qreal *stateVecImag = qureg.deviceStateVec.imag;
+
2745 
+
2746  thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
2747  if (thisTask>=numTasks) return;
+
2748  thisBlock = thisTask / sizeHalfBlock;
+
2749  index = thisBlock*sizeBlock + thisTask%sizeHalfBlock;
+
2750 
+
2751  if (outcome==0){
+
2752  stateVecReal[index]=stateVecReal[index]*renorm;
+
2753  stateVecImag[index]=stateVecImag[index]*renorm;
+
2754 
+
2755  stateVecReal[index+sizeHalfBlock]=0;
+
2756  stateVecImag[index+sizeHalfBlock]=0;
+
2757  } else if (outcome==1){
+
2758  stateVecReal[index]=0;
+
2759  stateVecImag[index]=0;
+
2760 
+
2761  stateVecReal[index+sizeHalfBlock]=stateVecReal[index+sizeHalfBlock]*renorm;
+
2762  stateVecImag[index+sizeHalfBlock]=stateVecImag[index+sizeHalfBlock]*renorm;
+
2763  }
+
2764 }
+
2765 
+
2766 /*
+
2767  * outcomeProb must accurately be the probability of that qubit outcome in the state-vector, or
+
2768  * else the state-vector will lose normalisation
+
2769  */
+
2770 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
+
2771 {
+
2772  int threadsPerCUDABlock, CUDABlocks;
+
2773  threadsPerCUDABlock = 128;
+
2774  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk>>1)/threadsPerCUDABlock);
+
2775  statevec_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, measureQubit, outcome, outcomeProb);
+
2776 }
+
2777 
+ +
2780  qreal outcomeProb, qreal* vecReal, qreal *vecImag, long long int numBasesToVisit,
+
2781  long long int part1, long long int part2, long long int part3,
+
2782  long long int rowBit, long long int colBit, long long int desired, long long int undesired)
+
2783 {
+
2784  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2785  if (scanInd >= numBasesToVisit) return;
2786 
-
2787  // renormalise desired outcome
-
2788  vecReal[base + desired] /= outcomeProb;
-
2789  vecImag[base + desired] /= outcomeProb;
-
2790 
-
2791  // kill undesired outcome
-
2792  vecReal[base + undesired] = 0;
-
2793  vecImag[base + undesired] = 0;
-
2794 
-
2795  // kill |..0..><..1..| states
-
2796  vecReal[base + colBit] = 0;
-
2797  vecImag[base + colBit] = 0;
-
2798  vecReal[base + rowBit] = 0;
-
2799  vecImag[base + rowBit] = 0;
-
2800 }
-
2801 
-
2803 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb) {
-
2804 
-
2805  int rowQubit = measureQubit + qureg.numQubitsRepresented;
+
2787  long long int base = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2788 
+
2789  // renormalise desired outcome
+
2790  vecReal[base + desired] /= outcomeProb;
+
2791  vecImag[base + desired] /= outcomeProb;
+
2792 
+
2793  // kill undesired outcome
+
2794  vecReal[base + undesired] = 0;
+
2795  vecImag[base + undesired] = 0;
+
2796 
+
2797  // kill |..0..><..1..| states
+
2798  vecReal[base + colBit] = 0;
+
2799  vecImag[base + colBit] = 0;
+
2800  vecReal[base + rowBit] = 0;
+
2801  vecImag[base + rowBit] = 0;
+
2802 }
+
2803 
+
2805 void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb) {
2806 
-
2807  int colBit = 1LL << measureQubit;
-
2808  int rowBit = 1LL << rowQubit;
-
2809 
-
2810  long long int numBasesToVisit = qureg.numAmpsPerChunk/4;
-
2811  long long int part1 = colBit -1;
-
2812  long long int part2 = (rowBit >> 1) - colBit;
-
2813  long long int part3 = numBasesToVisit - (rowBit >> 1);
-
2814 
-
2815  long long int desired, undesired;
-
2816  if (outcome == 0) {
-
2817  desired = 0;
-
2818  undesired = colBit | rowBit;
-
2819  } else {
-
2820  desired = colBit | rowBit;
-
2821  undesired = 0;
-
2822  }
-
2823 
-
2824  int threadsPerCUDABlock, CUDABlocks;
-
2825  threadsPerCUDABlock = 128;
-
2826  CUDABlocks = ceil(numBasesToVisit / (qreal) threadsPerCUDABlock);
-
2827  densmatr_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2828  outcomeProb, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBasesToVisit,
-
2829  part1, part2, part3, rowBit, colBit, desired, undesired);
-
2830 }
-
2831 
-
2832 __global__ void densmatr_mixDensityMatrixKernel(Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit) {
-
2833 
-
2834  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2835  if (ampInd >= numAmpsToVisit) return;
-
2836 
-
2837  combineQureg.deviceStateVec.real[ampInd] *= 1-otherProb;
-
2838  combineQureg.deviceStateVec.imag[ampInd] *= 1-otherProb;
-
2839 
-
2840  combineQureg.deviceStateVec.real[ampInd] += otherProb*otherQureg.deviceStateVec.real[ampInd];
-
2841  combineQureg.deviceStateVec.imag[ampInd] += otherProb*otherQureg.deviceStateVec.imag[ampInd];
-
2842 }
-
2843 
-
2844 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
-
2845 
-
2846  long long int numAmpsToVisit = combineQureg.numAmpsPerChunk;
+
2807  int rowQubit = measureQubit + qureg.numQubitsRepresented;
+
2808 
+
2809  int colBit = 1LL << measureQubit;
+
2810  int rowBit = 1LL << rowQubit;
+
2811 
+
2812  long long int numBasesToVisit = qureg.numAmpsPerChunk/4;
+
2813  long long int part1 = colBit -1;
+
2814  long long int part2 = (rowBit >> 1) - colBit;
+
2815  long long int part3 = numBasesToVisit - (rowBit >> 1);
+
2816 
+
2817  long long int desired, undesired;
+
2818  if (outcome == 0) {
+
2819  desired = 0;
+
2820  undesired = colBit | rowBit;
+
2821  } else {
+
2822  desired = colBit | rowBit;
+
2823  undesired = 0;
+
2824  }
+
2825 
+
2826  int threadsPerCUDABlock, CUDABlocks;
+
2827  threadsPerCUDABlock = 128;
+
2828  CUDABlocks = ceil(numBasesToVisit / (qreal) threadsPerCUDABlock);
+
2829  densmatr_collapseToKnownProbOutcomeKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2830  outcomeProb, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBasesToVisit,
+
2831  part1, part2, part3, rowBit, colBit, desired, undesired);
+
2832 }
+
2833 
+
2834 __global__ void densmatr_mixDensityMatrixKernel(Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit) {
+
2835 
+
2836  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2837  if (ampInd >= numAmpsToVisit) return;
+
2838 
+
2839  combineQureg.deviceStateVec.real[ampInd] *= 1-otherProb;
+
2840  combineQureg.deviceStateVec.imag[ampInd] *= 1-otherProb;
+
2841 
+
2842  combineQureg.deviceStateVec.real[ampInd] += otherProb*otherQureg.deviceStateVec.real[ampInd];
+
2843  combineQureg.deviceStateVec.imag[ampInd] += otherProb*otherQureg.deviceStateVec.imag[ampInd];
+
2844 }
+
2845 
+
2846 void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg) {
2847 
-
2848  int threadsPerCUDABlock, CUDABlocks;
-
2849  threadsPerCUDABlock = 128;
-
2850  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2851  densmatr_mixDensityMatrixKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2852  combineQureg, otherProb, otherQureg, numAmpsToVisit
-
2853  );
-
2854 }
-
2855 
- -
2862  qreal fac, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
2863  long long int part1, long long int part2, long long int part3,
-
2864  long long int colBit, long long int rowBit)
-
2865 {
-
2866  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2867  if (scanInd >= numAmpsToVisit) return;
-
2868 
-
2869  long long int ampInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2870  vecReal[ampInd + colBit] *= fac;
-
2871  vecImag[ampInd + colBit] *= fac;
-
2872  vecReal[ampInd + rowBit] *= fac;
-
2873  vecImag[ampInd + rowBit] *= fac;
-
2874 }
-
2875 
-
2876 
-
2877 void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac) {
-
2878 
-
2879  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
2848  long long int numAmpsToVisit = combineQureg.numAmpsPerChunk;
+
2849 
+
2850  int threadsPerCUDABlock, CUDABlocks;
+
2851  threadsPerCUDABlock = 128;
+
2852  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
2853  densmatr_mixDensityMatrixKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2854  combineQureg, otherProb, otherQureg, numAmpsToVisit
+
2855  );
+
2856 }
+
2857 
+ +
2864  qreal fac, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
+
2865  long long int part1, long long int part2, long long int part3,
+
2866  long long int colBit, long long int rowBit)
+
2867 {
+
2868  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2869  if (scanInd >= numAmpsToVisit) return;
+
2870 
+
2871  long long int ampInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2872  vecReal[ampInd + colBit] *= fac;
+
2873  vecImag[ampInd + colBit] *= fac;
+
2874  vecReal[ampInd + rowBit] *= fac;
+
2875  vecImag[ampInd + rowBit] *= fac;
+
2876 }
+
2877 
+
2878 
+
2879 void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac) {
2880 
-
2881  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
2882  long long int colBit = 1LL << targetQubit;
-
2883  long long int rowBit = 1LL << rowQubit;
-
2884 
-
2885  long long int part1 = colBit - 1;
-
2886  long long int part2 = (rowBit >> 1) - colBit;
-
2887  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
2888 
-
2889  int threadsPerCUDABlock, CUDABlocks;
-
2890  threadsPerCUDABlock = 128;
-
2891  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2892  densmatr_mixDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2893  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
2894  part1, part2, part3, colBit, rowBit);
-
2895 }
-
2896 
-
2897 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) {
-
2898 
-
2899  if (dephase == 0)
-
2900  return;
-
2901 
-
2902  qreal dephFac = 1 - dephase;
-
2903  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephFac);
-
2904 }
-
2905 
- -
2913  qreal fac, qreal* vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit,
-
2914  long long int part1, long long int part2, long long int part3, long long int part4, long long int part5,
-
2915  long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
-
2916 {
-
2917  long long int outerInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2918  if (outerInd >= numAmpsToVisit) return;
-
2919 
-
2920  // sets meta in 1...14 excluding 5, 10, creating bit string DCBA for |..D..C..><..B..A|
-
2921  int meta = 1 + (outerInd/numBackgroundStates);
-
2922  if (meta > 4) meta++;
-
2923  if (meta > 9) meta++;
-
2924 
-
2925  long long int shift = rowBit2*((meta>>3)%2) + rowBit1*((meta>>2)%2) + colBit2*((meta>>1)%2) + colBit1*(meta%2);
-
2926  long long int scanInd = outerInd % numBackgroundStates;
-
2927  long long int stateInd = (
-
2928  shift +
-
2929  (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4));
-
2930 
-
2931  vecReal[stateInd] *= fac;
-
2932  vecImag[stateInd] *= fac;
-
2933 }
-
2934 
-
2935 // @TODO is separating these 12 amplitudes really faster than letting every 16th base modify 12 elems?
-
2936 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) {
-
2937 
-
2938  if (dephase == 0)
-
2939  return;
-
2940 
-
2941  // assumes qubit2 > qubit1
+
2881  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
2882 
+
2883  int rowQubit = targetQubit + qureg.numQubitsRepresented;
+
2884  long long int colBit = 1LL << targetQubit;
+
2885  long long int rowBit = 1LL << rowQubit;
+
2886 
+
2887  long long int part1 = colBit - 1;
+
2888  long long int part2 = (rowBit >> 1) - colBit;
+
2889  long long int part3 = numAmpsToVisit - (rowBit >> 1);
+
2890 
+
2891  int threadsPerCUDABlock, CUDABlocks;
+
2892  threadsPerCUDABlock = 128;
+
2893  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
2894  densmatr_mixDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2895  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
2896  part1, part2, part3, colBit, rowBit);
+
2897 }
+
2898 
+
2899 void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase) {
+
2900 
+
2901  if (dephase == 0)
+
2902  return;
+
2903 
+
2904  qreal dephFac = 1 - dephase;
+
2905  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephFac);
+
2906 }
+
2907 
+ +
2915  qreal fac, qreal* vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit,
+
2916  long long int part1, long long int part2, long long int part3, long long int part4, long long int part5,
+
2917  long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
+
2918 {
+
2919  long long int outerInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2920  if (outerInd >= numAmpsToVisit) return;
+
2921 
+
2922  // sets meta in 1...14 excluding 5, 10, creating bit string DCBA for |..D..C..><..B..A|
+
2923  int meta = 1 + (outerInd/numBackgroundStates);
+
2924  if (meta > 4) meta++;
+
2925  if (meta > 9) meta++;
+
2926 
+
2927  long long int shift = rowBit2*((meta>>3)%2) + rowBit1*((meta>>2)%2) + colBit2*((meta>>1)%2) + colBit1*(meta%2);
+
2928  long long int scanInd = outerInd % numBackgroundStates;
+
2929  long long int stateInd = (
+
2930  shift +
+
2931  (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4));
+
2932 
+
2933  vecReal[stateInd] *= fac;
+
2934  vecImag[stateInd] *= fac;
+
2935 }
+
2936 
+
2937 // @TODO is separating these 12 amplitudes really faster than letting every 16th base modify 12 elems?
+
2938 void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase) {
+
2939 
+
2940  if (dephase == 0)
+
2941  return;
2942 
-
2943  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
2944  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
2945 
-
2946  long long int colBit1 = 1LL << qubit1;
-
2947  long long int rowBit1 = 1LL << rowQubit1;
-
2948  long long int colBit2 = 1LL << qubit2;
-
2949  long long int rowBit2 = 1LL << rowQubit2;
-
2950 
-
2951  long long int part1 = colBit1 - 1;
-
2952  long long int part2 = (colBit2 >> 1) - colBit1;
-
2953  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
2954  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
2955  long long int part5 = (qureg.numAmpsPerChunk/16) - (rowBit2 >> 3);
-
2956  qreal dephFac = 1 - dephase;
-
2957 
-
2958  // refers to states |a 0 b 0 c><d 0 e 0 f| (target qubits are fixed)
-
2959  long long int numBackgroundStates = qureg.numAmpsPerChunk/16;
-
2960 
-
2961  // 12 of these states experience dephasing
-
2962  long long int numAmpsToVisit = 12 * numBackgroundStates;
-
2963 
-
2964  int threadsPerCUDABlock, CUDABlocks;
-
2965  threadsPerCUDABlock = 128;
-
2966  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
2967  densmatr_mixTwoQubitDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
2968  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBackgroundStates, numAmpsToVisit,
-
2969  part1, part2, part3, part4, part5, colBit1, rowBit1, colBit2, rowBit2);
-
2970 }
-
2971 
- -
2974  qreal depolLevel, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
2975  long long int part1, long long int part2, long long int part3,
-
2976  long long int bothBits)
-
2977 {
-
2978  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
2979  if (scanInd >= numAmpsToVisit) return;
-
2980 
-
2981  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
2982  long long int targetInd = baseInd + bothBits;
-
2983 
-
2984  qreal realAvDepol = depolLevel * 0.5 * (vecReal[baseInd] + vecReal[targetInd]);
-
2985  qreal imagAvDepol = depolLevel * 0.5 * (vecImag[baseInd] + vecImag[targetInd]);
-
2986 
-
2987  vecReal[baseInd] *= 1 - depolLevel;
-
2988  vecImag[baseInd] *= 1 - depolLevel;
-
2989  vecReal[targetInd] *= 1 - depolLevel;
-
2990  vecImag[targetInd] *= 1 - depolLevel;
-
2991 
-
2992  vecReal[baseInd] += realAvDepol;
-
2993  vecImag[baseInd] += imagAvDepol;
-
2994  vecReal[targetInd] += realAvDepol;
-
2995  vecImag[targetInd] += imagAvDepol;
-
2996 }
-
2997 
- -
3000  qreal damping, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
3001  long long int part1, long long int part2, long long int part3,
-
3002  long long int bothBits)
-
3003 {
-
3004  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3005  if (scanInd >= numAmpsToVisit) return;
-
3006 
-
3007  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
-
3008  long long int targetInd = baseInd + bothBits;
-
3009 
-
3010  qreal realAvDepol = damping * ( vecReal[targetInd]);
-
3011  qreal imagAvDepol = damping * ( vecImag[targetInd]);
-
3012 
-
3013  vecReal[targetInd] *= 1 - damping;
-
3014  vecImag[targetInd] *= 1 - damping;
-
3015 
-
3016  vecReal[baseInd] += realAvDepol;
-
3017  vecImag[baseInd] += imagAvDepol;
-
3018 }
-
3019 
-
3020 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
-
3021 
-
3022  if (depolLevel == 0)
-
3023  return;
-
3024 
-
3025  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
2943  // assumes qubit2 > qubit1
+
2944 
+
2945  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
+
2946  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
+
2947 
+
2948  long long int colBit1 = 1LL << qubit1;
+
2949  long long int rowBit1 = 1LL << rowQubit1;
+
2950  long long int colBit2 = 1LL << qubit2;
+
2951  long long int rowBit2 = 1LL << rowQubit2;
+
2952 
+
2953  long long int part1 = colBit1 - 1;
+
2954  long long int part2 = (colBit2 >> 1) - colBit1;
+
2955  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
+
2956  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
+
2957  long long int part5 = (qureg.numAmpsPerChunk/16) - (rowBit2 >> 3);
+
2958  qreal dephFac = 1 - dephase;
+
2959 
+
2960  // refers to states |a 0 b 0 c><d 0 e 0 f| (target qubits are fixed)
+
2961  long long int numBackgroundStates = qureg.numAmpsPerChunk/16;
+
2962 
+
2963  // 12 of these states experience dephasing
+
2964  long long int numAmpsToVisit = 12 * numBackgroundStates;
+
2965 
+
2966  int threadsPerCUDABlock, CUDABlocks;
+
2967  threadsPerCUDABlock = 128;
+
2968  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
2969  densmatr_mixTwoQubitDephasingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
2970  dephFac, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numBackgroundStates, numAmpsToVisit,
+
2971  part1, part2, part3, part4, part5, colBit1, rowBit1, colBit2, rowBit2);
+
2972 }
+
2973 
+ +
2976  qreal depolLevel, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
+
2977  long long int part1, long long int part2, long long int part3,
+
2978  long long int bothBits)
+
2979 {
+
2980  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
2981  if (scanInd >= numAmpsToVisit) return;
+
2982 
+
2983  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
2984  long long int targetInd = baseInd + bothBits;
+
2985 
+
2986  qreal realAvDepol = depolLevel * 0.5 * (vecReal[baseInd] + vecReal[targetInd]);
+
2987  qreal imagAvDepol = depolLevel * 0.5 * (vecImag[baseInd] + vecImag[targetInd]);
+
2988 
+
2989  vecReal[baseInd] *= 1 - depolLevel;
+
2990  vecImag[baseInd] *= 1 - depolLevel;
+
2991  vecReal[targetInd] *= 1 - depolLevel;
+
2992  vecImag[targetInd] *= 1 - depolLevel;
+
2993 
+
2994  vecReal[baseInd] += realAvDepol;
+
2995  vecImag[baseInd] += imagAvDepol;
+
2996  vecReal[targetInd] += realAvDepol;
+
2997  vecImag[targetInd] += imagAvDepol;
+
2998 }
+
2999 
+ +
3002  qreal damping, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
+
3003  long long int part1, long long int part2, long long int part3,
+
3004  long long int bothBits)
+
3005 {
+
3006  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3007  if (scanInd >= numAmpsToVisit) return;
+
3008 
+
3009  long long int baseInd = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2);
+
3010  long long int targetInd = baseInd + bothBits;
+
3011 
+
3012  qreal realAvDepol = damping * ( vecReal[targetInd]);
+
3013  qreal imagAvDepol = damping * ( vecImag[targetInd]);
+
3014 
+
3015  vecReal[targetInd] *= 1 - damping;
+
3016  vecImag[targetInd] *= 1 - damping;
+
3017 
+
3018  vecReal[baseInd] += realAvDepol;
+
3019  vecImag[baseInd] += imagAvDepol;
+
3020 }
+
3021 
+
3022 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
+
3023 
+
3024  if (depolLevel == 0)
+
3025  return;
3026 
-
3027  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
3028  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
3029 
-
3030  long long int colBit = 1LL << targetQubit;
-
3031  long long int rowBit = 1LL << rowQubit;
-
3032  long long int bothBits = colBit | rowBit;
-
3033 
-
3034  long long int part1 = colBit - 1;
-
3035  long long int part2 = (rowBit >> 1) - colBit;
-
3036  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
3037 
-
3038  int threadsPerCUDABlock, CUDABlocks;
-
3039  threadsPerCUDABlock = 128;
-
3040  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3041  densmatr_mixDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3042  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
3043  part1, part2, part3, bothBits);
-
3044 }
-
3045 
-
3046 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
-
3047 
-
3048  if (damping == 0)
-
3049  return;
-
3050 
-
3051  qreal dephase = sqrt(1-damping);
-
3052  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
-
3053 
-
3054  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
-
3055  int rowQubit = targetQubit + qureg.numQubitsRepresented;
-
3056 
-
3057  long long int colBit = 1LL << targetQubit;
-
3058  long long int rowBit = 1LL << rowQubit;
-
3059  long long int bothBits = colBit | rowBit;
-
3060 
-
3061  long long int part1 = colBit - 1;
-
3062  long long int part2 = (rowBit >> 1) - colBit;
-
3063  long long int part3 = numAmpsToVisit - (rowBit >> 1);
-
3064 
-
3065  int threadsPerCUDABlock, CUDABlocks;
-
3066  threadsPerCUDABlock = 128;
-
3067  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3068  densmatr_mixDampingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3069  damping, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
3070  part1, part2, part3, bothBits);
-
3071 }
-
3072 
- -
3075  qreal depolLevel, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
-
3076  long long int part1, long long int part2, long long int part3,
-
3077  long long int part4, long long int part5,
-
3078  long long int rowCol1, long long int rowCol2)
-
3079 {
-
3080  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3081  if (scanInd >= numAmpsToVisit) return;
-
3082 
-
3083  // index of |..0..0..><..0..0|
-
3084  long long int ind00 = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4);
-
3085  long long int ind01 = ind00 + rowCol1;
-
3086  long long int ind10 = ind00 + rowCol2;
-
3087  long long int ind11 = ind00 + rowCol1 + rowCol2;
-
3088 
-
3089  qreal realAvDepol = depolLevel * 0.25 * (
-
3090  vecReal[ind00] + vecReal[ind01] + vecReal[ind10] + vecReal[ind11]);
-
3091  qreal imagAvDepol = depolLevel * 0.25 * (
-
3092  vecImag[ind00] + vecImag[ind01] + vecImag[ind10] + vecImag[ind11]);
-
3093 
-
3094  qreal retain = 1 - depolLevel;
-
3095  vecReal[ind00] *= retain; vecImag[ind00] *= retain;
-
3096  vecReal[ind01] *= retain; vecImag[ind01] *= retain;
-
3097  vecReal[ind10] *= retain; vecImag[ind10] *= retain;
-
3098  vecReal[ind11] *= retain; vecImag[ind11] *= retain;
-
3099 
-
3100  vecReal[ind00] += realAvDepol; vecImag[ind00] += imagAvDepol;
-
3101  vecReal[ind01] += realAvDepol; vecImag[ind01] += imagAvDepol;
-
3102  vecReal[ind10] += realAvDepol; vecImag[ind10] += imagAvDepol;
-
3103  vecReal[ind11] += realAvDepol; vecImag[ind11] += imagAvDepol;
-
3104 }
-
3105 
-
3106 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel) {
-
3107 
-
3108  if (depolLevel == 0)
-
3109  return;
-
3110 
-
3111  // assumes qubit2 > qubit1
+
3027  densmatr_mixDephasing(qureg, targetQubit, depolLevel);
+
3028 
+
3029  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
3030  int rowQubit = targetQubit + qureg.numQubitsRepresented;
+
3031 
+
3032  long long int colBit = 1LL << targetQubit;
+
3033  long long int rowBit = 1LL << rowQubit;
+
3034  long long int bothBits = colBit | rowBit;
+
3035 
+
3036  long long int part1 = colBit - 1;
+
3037  long long int part2 = (rowBit >> 1) - colBit;
+
3038  long long int part3 = numAmpsToVisit - (rowBit >> 1);
+
3039 
+
3040  int threadsPerCUDABlock, CUDABlocks;
+
3041  threadsPerCUDABlock = 128;
+
3042  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3043  densmatr_mixDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3044  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
3045  part1, part2, part3, bothBits);
+
3046 }
+
3047 
+
3048 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
+
3049 
+
3050  if (damping == 0)
+
3051  return;
+
3052 
+
3053  qreal dephase = sqrt(1-damping);
+
3054  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, dephase);
+
3055 
+
3056  long long int numAmpsToVisit = qureg.numAmpsPerChunk/4;
+
3057  int rowQubit = targetQubit + qureg.numQubitsRepresented;
+
3058 
+
3059  long long int colBit = 1LL << targetQubit;
+
3060  long long int rowBit = 1LL << rowQubit;
+
3061  long long int bothBits = colBit | rowBit;
+
3062 
+
3063  long long int part1 = colBit - 1;
+
3064  long long int part2 = (rowBit >> 1) - colBit;
+
3065  long long int part3 = numAmpsToVisit - (rowBit >> 1);
+
3066 
+
3067  int threadsPerCUDABlock, CUDABlocks;
+
3068  threadsPerCUDABlock = 128;
+
3069  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3070  densmatr_mixDampingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3071  damping, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
3072  part1, part2, part3, bothBits);
+
3073 }
+
3074 
+ +
3077  qreal depolLevel, qreal* vecReal, qreal *vecImag, long long int numAmpsToVisit,
+
3078  long long int part1, long long int part2, long long int part3,
+
3079  long long int part4, long long int part5,
+
3080  long long int rowCol1, long long int rowCol2)
+
3081 {
+
3082  long long int scanInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3083  if (scanInd >= numAmpsToVisit) return;
+
3084 
+
3085  // index of |..0..0..><..0..0|
+
3086  long long int ind00 = (scanInd&part1) + ((scanInd&part2)<<1) + ((scanInd&part3)<<2) + ((scanInd&part4)<<3) + ((scanInd&part5)<<4);
+
3087  long long int ind01 = ind00 + rowCol1;
+
3088  long long int ind10 = ind00 + rowCol2;
+
3089  long long int ind11 = ind00 + rowCol1 + rowCol2;
+
3090 
+
3091  qreal realAvDepol = depolLevel * 0.25 * (
+
3092  vecReal[ind00] + vecReal[ind01] + vecReal[ind10] + vecReal[ind11]);
+
3093  qreal imagAvDepol = depolLevel * 0.25 * (
+
3094  vecImag[ind00] + vecImag[ind01] + vecImag[ind10] + vecImag[ind11]);
+
3095 
+
3096  qreal retain = 1 - depolLevel;
+
3097  vecReal[ind00] *= retain; vecImag[ind00] *= retain;
+
3098  vecReal[ind01] *= retain; vecImag[ind01] *= retain;
+
3099  vecReal[ind10] *= retain; vecImag[ind10] *= retain;
+
3100  vecReal[ind11] *= retain; vecImag[ind11] *= retain;
+
3101 
+
3102  vecReal[ind00] += realAvDepol; vecImag[ind00] += imagAvDepol;
+
3103  vecReal[ind01] += realAvDepol; vecImag[ind01] += imagAvDepol;
+
3104  vecReal[ind10] += realAvDepol; vecImag[ind10] += imagAvDepol;
+
3105  vecReal[ind11] += realAvDepol; vecImag[ind11] += imagAvDepol;
+
3106 }
+
3107 
+
3108 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel) {
+
3109 
+
3110  if (depolLevel == 0)
+
3111  return;
3112 
-
3113  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
3113  // assumes qubit2 > qubit1
3114 
-
3115  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
-
3116  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
-
3117 
-
3118  long long int colBit1 = 1LL << qubit1;
-
3119  long long int rowBit1 = 1LL << rowQubit1;
-
3120  long long int colBit2 = 1LL << qubit2;
-
3121  long long int rowBit2 = 1LL << rowQubit2;
-
3122 
-
3123  long long int rowCol1 = colBit1 | rowBit1;
-
3124  long long int rowCol2 = colBit2 | rowBit2;
-
3125 
-
3126  long long int numAmpsToVisit = qureg.numAmpsPerChunk/16;
-
3127  long long int part1 = colBit1 - 1;
-
3128  long long int part2 = (colBit2 >> 1) - colBit1;
-
3129  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
-
3130  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
-
3131  long long int part5 = numAmpsToVisit - (rowBit2 >> 3);
-
3132 
-
3133  int threadsPerCUDABlock, CUDABlocks;
-
3134  threadsPerCUDABlock = 128;
-
3135  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3136  densmatr_mixTwoQubitDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3137  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
-
3138  part1, part2, part3, part4, part5, rowCol1, rowCol2);
-
3139 }
-
3140 
-
3141 __global__ void statevec_setWeightedQuregKernel(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
+
3115  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
3116 
+
3117  int rowQubit1 = qubit1 + qureg.numQubitsRepresented;
+
3118  int rowQubit2 = qubit2 + qureg.numQubitsRepresented;
+
3119 
+
3120  long long int colBit1 = 1LL << qubit1;
+
3121  long long int rowBit1 = 1LL << rowQubit1;
+
3122  long long int colBit2 = 1LL << qubit2;
+
3123  long long int rowBit2 = 1LL << rowQubit2;
+
3124 
+
3125  long long int rowCol1 = colBit1 | rowBit1;
+
3126  long long int rowCol2 = colBit2 | rowBit2;
+
3127 
+
3128  long long int numAmpsToVisit = qureg.numAmpsPerChunk/16;
+
3129  long long int part1 = colBit1 - 1;
+
3130  long long int part2 = (colBit2 >> 1) - colBit1;
+
3131  long long int part3 = (rowBit1 >> 2) - (colBit2 >> 1);
+
3132  long long int part4 = (rowBit2 >> 3) - (rowBit1 >> 2);
+
3133  long long int part5 = numAmpsToVisit - (rowBit2 >> 3);
+
3134 
+
3135  int threadsPerCUDABlock, CUDABlocks;
+
3136  threadsPerCUDABlock = 128;
+
3137  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3138  densmatr_mixTwoQubitDepolarisingKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3139  depolLevel, qureg.deviceStateVec.real, qureg.deviceStateVec.imag, numAmpsToVisit,
+
3140  part1, part2, part3, part4, part5, rowCol1, rowCol2);
+
3141 }
3142 
-
3143  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3144  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
-
3145  if (ampInd >= numAmpsToVisit) return;
-
3146 
-
3147  qreal *vecRe1 = qureg1.deviceStateVec.real;
-
3148  qreal *vecIm1 = qureg1.deviceStateVec.imag;
-
3149  qreal *vecRe2 = qureg2.deviceStateVec.real;
-
3150  qreal *vecIm2 = qureg2.deviceStateVec.imag;
-
3151  qreal *vecReOut = out.deviceStateVec.real;
-
3152  qreal *vecImOut = out.deviceStateVec.imag;
-
3153 
-
3154  qreal facRe1 = fac1.real;
-
3155  qreal facIm1 = fac1.imag;
-
3156  qreal facRe2 = fac2.real;
-
3157  qreal facIm2 = fac2.imag;
-
3158  qreal facReOut = facOut.real;
-
3159  qreal facImOut = facOut.imag;
-
3160 
-
3161  qreal re1,im1, re2,im2, reOut,imOut;
-
3162  long long int index = ampInd;
-
3163 
-
3164  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3165  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3166  reOut = vecReOut[index];
-
3167  imOut = vecImOut[index];
-
3168 
-
3169  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
3170  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
3171 }
-
3172 
-
3173 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
+
3143 __global__ void statevec_setWeightedQuregKernel(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
+
3144 
+
3145  long long int ampInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3146  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
+
3147  if (ampInd >= numAmpsToVisit) return;
+
3148 
+
3149  qreal *vecRe1 = qureg1.deviceStateVec.real;
+
3150  qreal *vecIm1 = qureg1.deviceStateVec.imag;
+
3151  qreal *vecRe2 = qureg2.deviceStateVec.real;
+
3152  qreal *vecIm2 = qureg2.deviceStateVec.imag;
+
3153  qreal *vecReOut = out.deviceStateVec.real;
+
3154  qreal *vecImOut = out.deviceStateVec.imag;
+
3155 
+
3156  qreal facRe1 = fac1.real;
+
3157  qreal facIm1 = fac1.imag;
+
3158  qreal facRe2 = fac2.real;
+
3159  qreal facIm2 = fac2.imag;
+
3160  qreal facReOut = facOut.real;
+
3161  qreal facImOut = facOut.imag;
+
3162 
+
3163  qreal re1,im1, re2,im2, reOut,imOut;
+
3164  long long int index = ampInd;
+
3165 
+
3166  re1 = vecRe1[index]; im1 = vecIm1[index];
+
3167  re2 = vecRe2[index]; im2 = vecIm2[index];
+
3168  reOut = vecReOut[index];
+
3169  imOut = vecImOut[index];
+
3170 
+
3171  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
+
3172  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
+
3173 }
3174 
-
3175  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
+
3175 void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out) {
3176 
-
3177  int threadsPerCUDABlock, CUDABlocks;
-
3178  threadsPerCUDABlock = 128;
-
3179  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
-
3180  statevec_setWeightedQuregKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
-
3181  fac1, qureg1, fac2, qureg2, facOut, out
-
3182  );
-
3183 }
-
3184 
- +
3177  long long int numAmpsToVisit = qureg1.numAmpsPerChunk;
+
3178 
+
3179  int threadsPerCUDABlock, CUDABlocks;
+
3180  threadsPerCUDABlock = 128;
+
3181  CUDABlocks = ceil(numAmpsToVisit / (qreal) threadsPerCUDABlock);
+
3182  statevec_setWeightedQuregKernel<<<CUDABlocks, threadsPerCUDABlock>>>(
+
3183  fac1, qureg1, fac2, qureg2, facOut, out
+
3184  );
+
3185 }
3186 
-
3187  // each thread modifies one value; a wasteful and inefficient strategy
-
3188  long long int numTasks = qureg.numAmpsPerChunk;
-
3189  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
3190  if (thisTask >= numTasks) return;
-
3191 
-
3192  qreal* stateRe = qureg.deviceStateVec.real;
-
3193  qreal* stateIm = qureg.deviceStateVec.imag;
-
3194  qreal* opRe = op.deviceOperator.real;
-
3195  qreal* opIm = op.deviceOperator.imag;
-
3196 
-
3197  qreal a = stateRe[thisTask];
-
3198  qreal b = stateIm[thisTask];
-
3199  qreal c = opRe[thisTask];
-
3200  qreal d = opIm[thisTask];
-
3201 
-
3202  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3203  stateRe[thisTask] = a*c - b*d;
-
3204  stateIm[thisTask] = a*d + b*c;
-
3205 }
-
3206 
- -
3208 {
-
3209  int threadsPerCUDABlock, CUDABlocks;
-
3210  threadsPerCUDABlock = 128;
-
3211  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
3212  statevec_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
3213 }
-
3214 
- + +
3188 
+
3189  // each thread modifies one value; a wasteful and inefficient strategy
+
3190  long long int numTasks = qureg.numAmpsPerChunk;
+
3191  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
3192  if (thisTask >= numTasks) return;
+
3193 
+
3194  qreal* stateRe = qureg.deviceStateVec.real;
+
3195  qreal* stateIm = qureg.deviceStateVec.imag;
+
3196  qreal* opRe = op.deviceOperator.real;
+
3197  qreal* opIm = op.deviceOperator.imag;
+
3198 
+
3199  qreal a = stateRe[thisTask];
+
3200  qreal b = stateIm[thisTask];
+
3201  qreal c = opRe[thisTask];
+
3202  qreal d = opIm[thisTask];
+
3203 
+
3204  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
3205  stateRe[thisTask] = a*c - b*d;
+
3206  stateIm[thisTask] = a*d + b*c;
+
3207 }
+
3208 
+ +
3210 {
+
3211  int threadsPerCUDABlock, CUDABlocks;
+
3212  threadsPerCUDABlock = 128;
+
3213  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
3214  statevec_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
+
3215 }
3216 
-
3217  // each thread modifies one value; a wasteful and inefficient strategy
-
3218  long long int numTasks = qureg.numAmpsPerChunk;
-
3219  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
-
3220  if (thisTask >= numTasks) return;
-
3221 
-
3222  qreal* stateRe = qureg.deviceStateVec.real;
-
3223  qreal* stateIm = qureg.deviceStateVec.imag;
-
3224  qreal* opRe = op.deviceOperator.real;
-
3225  qreal* opIm = op.deviceOperator.imag;
-
3226 
-
3227  int opDim = (1 << op.numQubits);
-
3228  qreal a = stateRe[thisTask];
-
3229  qreal b = stateIm[thisTask];
-
3230  qreal c = opRe[thisTask % opDim];
-
3231  qreal d = opIm[thisTask % opDim];
-
3232 
-
3233  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
3234  stateRe[thisTask] = a*c - b*d;
-
3235  stateIm[thisTask] = a*d + b*c;
-
3236 }
-
3237 
- -
3239 
-
3240  int threadsPerCUDABlock, CUDABlocks;
-
3241  threadsPerCUDABlock = 128;
-
3242  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
-
3243  densmatr_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
-
3244 }
-
3245 
- -
3248  int getRealComp,
-
3249  qreal* vecReal, qreal* vecImag, qreal* opReal, qreal* opImag,
-
3250  long long int numTermsToSum, qreal* reducedArray)
-
3251 {
-
3252  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3253  if (index >= numTermsToSum) return;
-
3254 
-
3255  qreal vecAbs = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+ +
3218 
+
3219  // each thread modifies one value; a wasteful and inefficient strategy
+
3220  long long int numTasks = qureg.numAmpsPerChunk;
+
3221  long long int thisTask = blockIdx.x*blockDim.x + threadIdx.x;
+
3222  if (thisTask >= numTasks) return;
+
3223 
+
3224  qreal* stateRe = qureg.deviceStateVec.real;
+
3225  qreal* stateIm = qureg.deviceStateVec.imag;
+
3226  qreal* opRe = op.deviceOperator.real;
+
3227  qreal* opIm = op.deviceOperator.imag;
+
3228 
+
3229  int opDim = (1 << op.numQubits);
+
3230  qreal a = stateRe[thisTask];
+
3231  qreal b = stateIm[thisTask];
+
3232  qreal c = opRe[thisTask % opDim];
+
3233  qreal d = opIm[thisTask % opDim];
+
3234 
+
3235  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
3236  stateRe[thisTask] = a*c - b*d;
+
3237  stateIm[thisTask] = a*d + b*c;
+
3238 }
+
3239 
+ +
3241 
+
3242  int threadsPerCUDABlock, CUDABlocks;
+
3243  threadsPerCUDABlock = 128;
+
3244  CUDABlocks = ceil((qreal)(qureg.numAmpsPerChunk)/threadsPerCUDABlock);
+
3245  densmatr_applyDiagonalOpKernel<<<CUDABlocks, threadsPerCUDABlock>>>(qureg, op);
+
3246 }
+
3247 
+ +
3250  int getRealComp,
+
3251  qreal* vecReal, qreal* vecImag, qreal* opReal, qreal* opImag,
+
3252  long long int numTermsToSum, qreal* reducedArray)
+
3253 {
+
3254  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3255  if (index >= numTermsToSum) return;
3256 
-
3257  // choose whether to calculate the real or imaginary term of the expec term
-
3258  qreal expecVal;
-
3259  if (getRealComp)
-
3260  expecVal = vecAbs * opReal[index];
-
3261  else
-
3262  expecVal = vecAbs * opImag[index];
-
3263 
-
3264  // array of each thread's collected sum term, to be summed
-
3265  extern __shared__ qreal tempReductionArray[];
-
3266  tempReductionArray[threadIdx.x] = expecVal;
-
3267  __syncthreads();
-
3268 
-
3269  // every second thread reduces
-
3270  if (threadIdx.x<blockDim.x/2)
-
3271  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3272 }
-
3273 
- -
3275 
-
3276  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3277  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3278  */
-
3279 
-
3280  qreal expecReal, expecImag;
-
3281 
-
3282  int getRealComp;
-
3283  long long int numValuesToReduce;
-
3284  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3285  int maxReducedPerLevel;
-
3286  int firstTime;
-
3287 
-
3288  // compute real component of inner product
-
3289  getRealComp = 1;
-
3290  numValuesToReduce = qureg.numAmpsPerChunk;
-
3291  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3292  firstTime = 1;
-
3293  while (numValuesToReduce > 1) {
-
3294  if (numValuesToReduce < maxReducedPerLevel) {
-
3295  valuesPerCUDABlock = numValuesToReduce;
-
3296  numCUDABlocks = 1;
-
3297  }
-
3298  else {
-
3299  valuesPerCUDABlock = maxReducedPerLevel;
-
3300  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3301  }
-
3302  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3303  if (firstTime) {
-
3304  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3305  getRealComp,
-
3306  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3307  op.deviceOperator.real, op.deviceOperator.imag,
-
3308  numValuesToReduce,
-
3309  qureg.firstLevelReduction);
-
3310  firstTime = 0;
-
3311  } else {
-
3312  cudaDeviceSynchronize();
-
3313  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3314  qureg.firstLevelReduction,
-
3315  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3316  cudaDeviceSynchronize();
- -
3318  }
-
3319  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3320  }
-
3321  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3322 
-
3323  // compute imag component of inner product
-
3324  getRealComp = 0;
-
3325  numValuesToReduce = qureg.numAmpsPerChunk;
-
3326  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3327  firstTime = 1;
-
3328  while (numValuesToReduce > 1) {
-
3329  if (numValuesToReduce < maxReducedPerLevel) {
-
3330  valuesPerCUDABlock = numValuesToReduce;
-
3331  numCUDABlocks = 1;
-
3332  }
-
3333  else {
-
3334  valuesPerCUDABlock = maxReducedPerLevel;
-
3335  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3336  }
-
3337  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3338  if (firstTime) {
-
3339  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3340  getRealComp,
-
3341  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3342  op.deviceOperator.real, op.deviceOperator.imag,
-
3343  numValuesToReduce,
-
3344  qureg.firstLevelReduction);
-
3345  firstTime = 0;
-
3346  } else {
-
3347  cudaDeviceSynchronize();
-
3348  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3349  qureg.firstLevelReduction,
-
3350  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3351  cudaDeviceSynchronize();
- -
3353  }
-
3354  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3355  }
-
3356  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3357 
-
3358  // return complex
-
3359  Complex expecVal;
-
3360  expecVal.real = expecReal;
-
3361  expecVal.imag = expecImag;
-
3362  return expecVal;
-
3363 }
-
3364 
- -
3366  int getRealComp,
-
3367  qreal* matReal, qreal* matImag, qreal* opReal, qreal* opImag,
-
3368  int numQubits, long long int numTermsToSum, qreal* reducedArray)
-
3369 {
-
3375  // index will identy one of the 2^Q diagonals to be summed
-
3376  long long int matInd = blockIdx.x*blockDim.x + threadIdx.x;
-
3377  if (matInd >= numTermsToSum) return;
-
3378 
-
3379  long long int diagSpacing = (1LL << numQubits) + 1LL;
-
3380  int isDiag = ((matInd % diagSpacing) == 0);
-
3381 
-
3382  long long int opInd = matInd / diagSpacing;
+
3257  qreal vecAbs = vecReal[index]*vecReal[index] + vecImag[index]*vecImag[index];
+
3258 
+
3259  // choose whether to calculate the real or imaginary term of the expec term
+
3260  qreal expecVal;
+
3261  if (getRealComp)
+
3262  expecVal = vecAbs * opReal[index];
+
3263  else
+
3264  expecVal = vecAbs * opImag[index];
+
3265 
+
3266  // array of each thread's collected sum term, to be summed
+
3267  extern __shared__ qreal tempReductionArray[];
+
3268  tempReductionArray[threadIdx.x] = expecVal;
+
3269  __syncthreads();
+
3270 
+
3271  // every second thread reduces
+
3272  if (threadIdx.x<blockDim.x/2)
+
3273  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
3274 }
+
3275 
+ +
3277 
+
3278  /* @TODO: remove all this reduction boilerplate from QuEST GPU
+
3279  * (e.g. a func which accepts a pointer to do every-value reduction?)
+
3280  */
+
3281 
+
3282  qreal expecReal, expecImag;
+
3283 
+
3284  int getRealComp;
+
3285  long long int numValuesToReduce;
+
3286  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
3287  int maxReducedPerLevel;
+
3288  int firstTime;
+
3289 
+
3290  // compute real component of inner product
+
3291  getRealComp = 1;
+
3292  numValuesToReduce = qureg.numAmpsPerChunk;
+
3293  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3294  firstTime = 1;
+
3295  while (numValuesToReduce > 1) {
+
3296  if (numValuesToReduce < maxReducedPerLevel) {
+
3297  valuesPerCUDABlock = numValuesToReduce;
+
3298  numCUDABlocks = 1;
+
3299  }
+
3300  else {
+
3301  valuesPerCUDABlock = maxReducedPerLevel;
+
3302  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3303  }
+
3304  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3305  if (firstTime) {
+
3306  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3307  getRealComp,
+
3308  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3309  op.deviceOperator.real, op.deviceOperator.imag,
+
3310  numValuesToReduce,
+
3311  qureg.firstLevelReduction);
+
3312  firstTime = 0;
+
3313  } else {
+
3314  cudaDeviceSynchronize();
+
3315  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3316  qureg.firstLevelReduction,
+
3317  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3318  cudaDeviceSynchronize();
+ +
3320  }
+
3321  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3322  }
+
3323  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3324 
+
3325  // compute imag component of inner product
+
3326  getRealComp = 0;
+
3327  numValuesToReduce = qureg.numAmpsPerChunk;
+
3328  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3329  firstTime = 1;
+
3330  while (numValuesToReduce > 1) {
+
3331  if (numValuesToReduce < maxReducedPerLevel) {
+
3332  valuesPerCUDABlock = numValuesToReduce;
+
3333  numCUDABlocks = 1;
+
3334  }
+
3335  else {
+
3336  valuesPerCUDABlock = maxReducedPerLevel;
+
3337  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3338  }
+
3339  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3340  if (firstTime) {
+
3341  statevec_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3342  getRealComp,
+
3343  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3344  op.deviceOperator.real, op.deviceOperator.imag,
+
3345  numValuesToReduce,
+
3346  qureg.firstLevelReduction);
+
3347  firstTime = 0;
+
3348  } else {
+
3349  cudaDeviceSynchronize();
+
3350  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3351  qureg.firstLevelReduction,
+
3352  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3353  cudaDeviceSynchronize();
+ +
3355  }
+
3356  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3357  }
+
3358  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3359 
+
3360  // return complex
+
3361  Complex expecVal;
+
3362  expecVal.real = expecReal;
+
3363  expecVal.imag = expecImag;
+
3364  return expecVal;
+
3365 }
+
3366 
+ +
3368  int getRealComp,
+
3369  qreal* matReal, qreal* matImag, qreal* opReal, qreal* opImag,
+
3370  int numQubits, long long int numTermsToSum, qreal* reducedArray)
+
3371 {
+
3377  // index will identy one of the 2^Q diagonals to be summed
+
3378  long long int matInd = blockIdx.x*blockDim.x + threadIdx.x;
+
3379  if (matInd >= numTermsToSum) return;
+
3380 
+
3381  long long int diagSpacing = (1LL << numQubits) + 1LL;
+
3382  int isDiag = ((matInd % diagSpacing) == 0);
3383 
-
3384  qreal val = 0;
-
3385  if (isDiag) {
-
3386 
-
3387  qreal matRe = matReal[matInd];
-
3388  qreal matIm = matImag[matInd];
-
3389  qreal opRe = opReal[opInd];
-
3390  qreal opIm = opImag[opInd];
-
3391 
-
3392  // (matRe + matIm i)(opRe + opIm i) =
-
3393  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
-
3394  if (getRealComp)
-
3395  val = matRe * opRe - matIm * opIm;
-
3396  else
-
3397  val = matRe * opIm + matIm * opRe;
-
3398  }
-
3399 
-
3400  // array of each thread's collected sum term, to be summed
-
3401  extern __shared__ qreal tempReductionArray[];
-
3402  tempReductionArray[threadIdx.x] = val;
-
3403  __syncthreads();
-
3404 
-
3405  // every second thread reduces
-
3406  if (threadIdx.x<blockDim.x/2)
-
3407  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
-
3408 }
-
3409 
- -
3411 
-
3412  /* @TODO: remove all this reduction boilerplate from QuEST GPU
-
3413  * (e.g. a func which accepts a pointer to do every-value reduction?)
-
3414  */
-
3415 
-
3416  qreal expecReal, expecImag;
-
3417 
-
3418  int getRealComp;
-
3419  long long int numValuesToReduce;
-
3420  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
-
3421  int maxReducedPerLevel;
-
3422  int firstTime;
-
3423 
-
3424  // compute real component of inner product
-
3425  getRealComp = 1;
-
3426  numValuesToReduce = qureg.numAmpsPerChunk;
-
3427  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3428  firstTime = 1;
-
3429  while (numValuesToReduce > 1) {
-
3430  if (numValuesToReduce < maxReducedPerLevel) {
-
3431  valuesPerCUDABlock = numValuesToReduce;
-
3432  numCUDABlocks = 1;
-
3433  }
-
3434  else {
-
3435  valuesPerCUDABlock = maxReducedPerLevel;
-
3436  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3437  }
-
3438  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3439  if (firstTime) {
-
3440  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3441  getRealComp,
-
3442  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3443  op.deviceOperator.real, op.deviceOperator.imag,
-
3444  op.numQubits, numValuesToReduce,
-
3445  qureg.firstLevelReduction);
-
3446  firstTime = 0;
-
3447  } else {
-
3448  cudaDeviceSynchronize();
-
3449  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3450  qureg.firstLevelReduction,
-
3451  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3452  cudaDeviceSynchronize();
- -
3454  }
-
3455  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3456  }
-
3457  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3458 
-
3459  // compute imag component of inner product
-
3460  getRealComp = 0;
-
3461  numValuesToReduce = qureg.numAmpsPerChunk;
-
3462  maxReducedPerLevel = REDUCE_SHARED_SIZE;
-
3463  firstTime = 1;
-
3464  while (numValuesToReduce > 1) {
-
3465  if (numValuesToReduce < maxReducedPerLevel) {
-
3466  valuesPerCUDABlock = numValuesToReduce;
-
3467  numCUDABlocks = 1;
-
3468  }
-
3469  else {
-
3470  valuesPerCUDABlock = maxReducedPerLevel;
-
3471  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
-
3472  }
-
3473  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
-
3474  if (firstTime) {
-
3475  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
-
3476  getRealComp,
-
3477  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
-
3478  op.deviceOperator.real, op.deviceOperator.imag,
-
3479  op.numQubits, numValuesToReduce,
-
3480  qureg.firstLevelReduction);
-
3481  firstTime = 0;
-
3482  } else {
-
3483  cudaDeviceSynchronize();
-
3484  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
-
3485  qureg.firstLevelReduction,
-
3486  qureg.secondLevelReduction, valuesPerCUDABlock);
-
3487  cudaDeviceSynchronize();
- -
3489  }
-
3490  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
-
3491  }
-
3492  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
-
3493 
-
3494  // return complex
-
3495  Complex expecVal;
-
3496  expecVal.real = expecReal;
-
3497  expecVal.imag = expecImag;
-
3498  return expecVal;
-
3499 }
-
3500 
-
3501 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
+
3384  long long int opInd = matInd / diagSpacing;
+
3385 
+
3386  qreal val = 0;
+
3387  if (isDiag) {
+
3388 
+
3389  qreal matRe = matReal[matInd];
+
3390  qreal matIm = matImag[matInd];
+
3391  qreal opRe = opReal[opInd];
+
3392  qreal opIm = opImag[opInd];
+
3393 
+
3394  // (matRe + matIm i)(opRe + opIm i) =
+
3395  // (matRe opRe - matIm opIm) + i (matRe opIm + matIm opRe)
+
3396  if (getRealComp)
+
3397  val = matRe * opRe - matIm * opIm;
+
3398  else
+
3399  val = matRe * opIm + matIm * opRe;
+
3400  }
+
3401 
+
3402  // array of each thread's collected sum term, to be summed
+
3403  extern __shared__ qreal tempReductionArray[];
+
3404  tempReductionArray[threadIdx.x] = val;
+
3405  __syncthreads();
+
3406 
+
3407  // every second thread reduces
+
3408  if (threadIdx.x<blockDim.x/2)
+
3409  reduceBlock(tempReductionArray, reducedArray, blockDim.x);
+
3410 }
+
3411 
+ +
3413 
+
3414  /* @TODO: remove all this reduction boilerplate from QuEST GPU
+
3415  * (e.g. a func which accepts a pointer to do every-value reduction?)
+
3416  */
+
3417 
+
3418  qreal expecReal, expecImag;
+
3419 
+
3420  int getRealComp;
+
3421  long long int numValuesToReduce;
+
3422  int valuesPerCUDABlock, numCUDABlocks, sharedMemSize;
+
3423  int maxReducedPerLevel;
+
3424  int firstTime;
+
3425 
+
3426  // compute real component of inner product
+
3427  getRealComp = 1;
+
3428  numValuesToReduce = qureg.numAmpsPerChunk;
+
3429  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3430  firstTime = 1;
+
3431  while (numValuesToReduce > 1) {
+
3432  if (numValuesToReduce < maxReducedPerLevel) {
+
3433  valuesPerCUDABlock = numValuesToReduce;
+
3434  numCUDABlocks = 1;
+
3435  }
+
3436  else {
+
3437  valuesPerCUDABlock = maxReducedPerLevel;
+
3438  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3439  }
+
3440  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3441  if (firstTime) {
+
3442  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3443  getRealComp,
+
3444  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3445  op.deviceOperator.real, op.deviceOperator.imag,
+
3446  op.numQubits, numValuesToReduce,
+
3447  qureg.firstLevelReduction);
+
3448  firstTime = 0;
+
3449  } else {
+
3450  cudaDeviceSynchronize();
+
3451  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3452  qureg.firstLevelReduction,
+
3453  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3454  cudaDeviceSynchronize();
+ +
3456  }
+
3457  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3458  }
+
3459  cudaMemcpy(&expecReal, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3460 
+
3461  // compute imag component of inner product
+
3462  getRealComp = 0;
+
3463  numValuesToReduce = qureg.numAmpsPerChunk;
+
3464  maxReducedPerLevel = REDUCE_SHARED_SIZE;
+
3465  firstTime = 1;
+
3466  while (numValuesToReduce > 1) {
+
3467  if (numValuesToReduce < maxReducedPerLevel) {
+
3468  valuesPerCUDABlock = numValuesToReduce;
+
3469  numCUDABlocks = 1;
+
3470  }
+
3471  else {
+
3472  valuesPerCUDABlock = maxReducedPerLevel;
+
3473  numCUDABlocks = ceil((qreal)numValuesToReduce/valuesPerCUDABlock);
+
3474  }
+
3475  sharedMemSize = valuesPerCUDABlock*sizeof(qreal);
+
3476  if (firstTime) {
+
3477  densmatr_calcExpecDiagonalOpKernel<<<numCUDABlocks, valuesPerCUDABlock, sharedMemSize>>>(
+
3478  getRealComp,
+
3479  qureg.deviceStateVec.real, qureg.deviceStateVec.imag,
+
3480  op.deviceOperator.real, op.deviceOperator.imag,
+
3481  op.numQubits, numValuesToReduce,
+
3482  qureg.firstLevelReduction);
+
3483  firstTime = 0;
+
3484  } else {
+
3485  cudaDeviceSynchronize();
+
3486  copySharedReduceBlock<<<numCUDABlocks, valuesPerCUDABlock/2, sharedMemSize>>>(
+
3487  qureg.firstLevelReduction,
+
3488  qureg.secondLevelReduction, valuesPerCUDABlock);
+
3489  cudaDeviceSynchronize();
+ +
3491  }
+
3492  numValuesToReduce = numValuesToReduce/maxReducedPerLevel;
+
3493  }
+
3494  cudaMemcpy(&expecImag, qureg.firstLevelReduction, sizeof(qreal), cudaMemcpyDeviceToHost);
+
3495 
+
3496  // return complex
+
3497  Complex expecVal;
+
3498  expecVal.real = expecReal;
+
3499  expecVal.imag = expecImag;
+
3500  return expecVal;
+
3501 }
3502 
-
3503  // update both RAM and VRAM, for consistency
-
3504  memcpy(&op.real[startInd], real, numElems * sizeof(qreal));
-
3505  memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal));
-
3506 
-
3507  cudaDeviceSynchronize();
-
3508  cudaMemcpy(
-
3509  op.deviceOperator.real + startInd,
-
3510  real,
-
3511  numElems * sizeof(*(op.deviceOperator.real)),
-
3512  cudaMemcpyHostToDevice);
-
3513  cudaMemcpy(
-
3514  op.deviceOperator.imag + startInd,
-
3515  imag,
-
3516  numElems * sizeof(*(op.deviceOperator.imag)),
-
3517  cudaMemcpyHostToDevice);
-
3518 }
-
3519 
- -
3521  Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding,
-
3522  qreal* coeffs, qreal* exponents, int numTerms,
-
3523  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
3524  int conj
-
3525 ) {
-
3526  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3527  if (index>=qureg.numAmpsPerChunk) return;
-
3528 
-
3529  // determine global amplitude index (non-distributed, so it's just local index)
-
3530  long long int globalAmpInd = index;
-
3531 
-
3532  // determine phase index of {qubits}
-
3533  long long int phaseInd = 0LL;
-
3534  if (encoding == UNSIGNED) {
-
3535  for (int q=0; q<numQubits; q++)
-
3536  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
3537  }
-
3538  else if (encoding == TWOS_COMPLEMENT) {
-
3539  for (int q=0; q<numQubits-1; q++) // use final qubit to indicate sign
-
3540  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
3541  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
-
3542  phaseInd -= (1LL << (numQubits-1));
-
3543  }
-
3544 
-
3545  // determine if this phase index has an overriden value (i < numOverrides)
-
3546  int i;
-
3547  for (i=0; i<numOverrides; i++)
-
3548  if (phaseInd == overrideInds[i])
-
3549  break;
-
3550 
-
3551  // determine phase from {coeffs}, {exponents} (unless overriden)
-
3552  qreal phase = 0;
-
3553  if (i < numOverrides)
-
3554  phase = overridePhases[i];
-
3555  else
-
3556  for (int t=0; t<numTerms; t++)
-
3557  phase += coeffs[t] * pow(phaseInd, exponents[t]);
-
3558 
-
3559  // negate phase to conjugate operator
-
3560  if (conj)
-
3561  phase *= -1;
-
3562 
-
3563  // modify amp to amp * exp(i phase)
-
3564  qreal c = cos(phase);
-
3565  qreal s = sin(phase);
-
3566  qreal re = qureg.deviceStateVec.real[index];
-
3567  qreal im = qureg.deviceStateVec.imag[index];
-
3568 
-
3569  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
3570  qureg.deviceStateVec.real[index] = re*c - im*s;
-
3571  qureg.deviceStateVec.imag[index] = re*s + im*c;
-
3572 }
-
3573 
- -
3575  Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding,
-
3576  qreal* coeffs, qreal* exponents, int numTerms,
-
3577  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
3578  int conj
-
3579  ) {
-
3580  // allocate device space for global list of {qubits}, {coeffs}, {exponents}, {overrideInds} and {overridePhases}
-
3581  int* d_qubits; size_t mem_qubits = numQubits * sizeof *d_qubits;
-
3582  qreal* d_coeffs; size_t mem_terms = numTerms * sizeof *d_coeffs;
-
3583  qreal* d_exponents;
-
3584  long long int* d_overrideInds; size_t mem_inds = numOverrides * sizeof *d_overrideInds;
-
3585  qreal* d_overridePhases; size_t mem_phas = numOverrides * sizeof *d_overridePhases;
-
3586  cudaMalloc(&d_qubits, mem_qubits); cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
3587  cudaMalloc(&d_coeffs, mem_terms); cudaMemcpy(d_coeffs, coeffs, mem_terms, cudaMemcpyHostToDevice);
-
3588  cudaMalloc(&d_exponents, mem_terms); cudaMemcpy(d_exponents, exponents, mem_terms, cudaMemcpyHostToDevice);
-
3589  cudaMalloc(&d_overrideInds, mem_inds); cudaMemcpy(d_overrideInds, overrideInds, mem_inds, cudaMemcpyHostToDevice);
-
3590  cudaMalloc(&d_overridePhases,mem_phas); cudaMemcpy(d_overridePhases, overridePhases, mem_phas, cudaMemcpyHostToDevice);
-
3591 
-
3592  // call kernel
-
3593  int threadsPerCUDABlock = 128;
-
3594  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
-
3595  statevec_applyPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
3596  qureg, d_qubits, numQubits, encoding,
-
3597  d_coeffs, d_exponents, numTerms,
-
3598  d_overrideInds, d_overridePhases, numOverrides,
-
3599  conj);
-
3600 
-
3601  // cleanup device memory
-
3602  cudaFree(d_qubits);
-
3603  cudaFree(d_coeffs);
-
3604  cudaFree(d_exponents);
-
3605  cudaFree(d_overrideInds);
-
3606  cudaFree(d_overridePhases);
-
3607 }
-
3608 
- -
3610  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
-
3611  qreal* coeffs, qreal* exponents, int* numTermsPerReg,
-
3612  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
3613  long long int *phaseInds,
-
3614  int conj
-
3615 ) {
-
3616  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3617  if (index>=qureg.numAmpsPerChunk) return;
-
3618 
-
3619  // determine global amplitude index (non-distributed, so it's just local index)
-
3620  long long int globalAmpInd = index;
-
3621 
-
3622  /*
-
3623  * each thread needs to write to a local:
-
3624  * long long int phaseInds[numRegs];
-
3625  * but instead has access to shared array phaseInds, with below stride and offset
-
3626  */
-
3627  size_t stride = gridDim.x*blockDim.x;
-
3628  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
3629 
-
3630  // determine phase indices
-
3631  int flatInd = 0;
-
3632  if (encoding == UNSIGNED) {
-
3633  for (int r=0; r<numRegs; r++) {
-
3634  phaseInds[r*stride+offset] = 0LL;
-
3635  for (int q=0; q<numQubitsPerReg[r]; q++)
-
3636  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3637  }
-
3638  }
-
3639  else if (encoding == TWOS_COMPLEMENT) {
-
3640  for (int r=0; r<numRegs; r++) {
-
3641  phaseInds[r*stride+offset] = 0LL;
-
3642  for (int q=0; q<numQubitsPerReg[r]-1; q++)
-
3643  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3644  // use final qubit to indicate sign
-
3645  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
3646  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
-
3647  }
-
3648  }
-
3649 
-
3650  // determine if this phase index has an overriden value (i < numOverrides)
-
3651  int i;
-
3652  for (i=0; i<numOverrides; i++) {
-
3653  int found = 1;
-
3654  for (int r=0; r<numRegs; r++) {
-
3655  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
-
3656  found = 0;
-
3657  break;
-
3658  }
-
3659  }
-
3660  if (found)
-
3661  break;
-
3662  }
-
3663 
-
3664  // compute the phase (unless overriden)
-
3665  qreal phase = 0;
-
3666  if (i < numOverrides)
-
3667  phase = overridePhases[i];
-
3668  else {
-
3669  flatInd = 0;
-
3670  for (int r=0; r<numRegs; r++) {
-
3671  for (int t=0; t<numTermsPerReg[r]; t++) {
-
3672  phase += coeffs[flatInd] * pow(phaseInds[r*stride+offset], exponents[flatInd]);
-
3673  flatInd++;
-
3674  }
-
3675  }
-
3676  }
-
3677 
-
3678  // negate phase to conjugate operator
-
3679  if (conj)
-
3680  phase *= -1;
-
3681 
-
3682  // modify amp to amp * exp(i phase)
-
3683  qreal c = cos(phase);
-
3684  qreal s = sin(phase);
-
3685  qreal re = qureg.deviceStateVec.real[index];
-
3686  qreal im = qureg.deviceStateVec.imag[index];
-
3687 
-
3688  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
3689  qureg.deviceStateVec.real[index] = re*c - im*s;
-
3690  qureg.deviceStateVec.imag[index] = re*s + im*c;
-
3691 }
-
3692 
- -
3694  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
-
3695  qreal* coeffs, qreal* exponents, int* numTermsPerReg,
-
3696  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
3697  int conj
-
3698 ) {
-
3699  // determine size of arrays, for cloning into GPU memory
-
3700  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
-
3701  size_t mem_numTermsPerReg = numRegs * sizeof *numTermsPerReg;
-
3702  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
-
3703  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
-
3704  size_t mem_qubits = 0;
-
3705  size_t mem_coeffs = 0;
-
3706  size_t mem_exponents = 0;
-
3707  for (int r=0; r<numRegs; r++) {
-
3708  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
-
3709  mem_coeffs += numTermsPerReg[r] * sizeof *coeffs;
-
3710  mem_exponents += numTermsPerReg[r] * sizeof *exponents;
-
3711  }
-
3712 
-
3713  // allocate global GPU memory
-
3714  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
-
3715  qreal* d_coeffs; cudaMalloc(&d_coeffs, mem_coeffs);
-
3716  qreal* d_exponents; cudaMalloc(&d_exponents, mem_exponents);
-
3717  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
-
3718  int* d_numTermsPerReg; cudaMalloc(&d_numTermsPerReg, mem_numTermsPerReg);
-
3719  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
-
3720  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
-
3721 
-
3722  // copy function args into GPU memory
-
3723  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
3724  cudaMemcpy(d_coeffs, coeffs, mem_coeffs, cudaMemcpyHostToDevice);
-
3725  cudaMemcpy(d_exponents, exponents, mem_exponents, cudaMemcpyHostToDevice);
-
3726  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
-
3727  cudaMemcpy(d_numTermsPerReg, numTermsPerReg, mem_numTermsPerReg, cudaMemcpyHostToDevice);
-
3728  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
-
3729  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
-
3730 
-
3731  int threadsPerCUDABlock = 128;
-
3732  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
-
3733 
-
3734  // allocate thread-local working space {phaseInds}
-
3735  long long int *d_phaseInds;
-
3736  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
3737  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
-
3738 
-
3739  // call kernel
-
3740  statevec_applyMultiVarPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
3741  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
-
3742  d_coeffs, d_exponents, d_numTermsPerReg,
-
3743  d_overrideInds, d_overridePhases, numOverrides,
-
3744  d_phaseInds,
-
3745  conj);
-
3746 
-
3747  // free device memory
-
3748  cudaFree(d_qubits);
-
3749  cudaFree(d_coeffs);
-
3750  cudaFree(d_exponents);
-
3751  cudaFree(d_numQubitsPerReg);
-
3752  cudaFree(d_numTermsPerReg);
-
3753  cudaFree(d_overrideInds);
-
3754  cudaFree(d_overridePhases);
-
3755  cudaFree(d_phaseInds);
-
3756 }
-
3757 
- -
3759  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
-
3760  enum phaseFunc phaseFuncName, qreal* params, int numParams,
-
3761  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
3762  long long int* phaseInds,
-
3763  int conj
-
3764 ) {
-
3765  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
-
3766  if (index>=qureg.numAmpsPerChunk) return;
-
3767 
-
3768  // determine global amplitude index (non-distributed, so it's just local index)
-
3769  long long int globalAmpInd = index;
-
3770 
-
3771  /*
-
3772  * each thread needs to write to a local:
-
3773  * long long int phaseInds[numRegs];
-
3774  * but instead has access to shared array phaseInds, with below stride and offset
-
3775  */
-
3776  size_t stride = gridDim.x*blockDim.x;
-
3777  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
-
3778 
-
3779  // determine phase indices
-
3780  if (encoding == UNSIGNED) {
-
3781  int flatInd = 0;
-
3782  for (int r=0; r<numRegs; r++) {
-
3783  phaseInds[r*stride+offset] = 0LL;
-
3784  for (int q=0; q<numQubitsPerReg[r]; q++)
-
3785  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3786  }
-
3787  }
-
3788  else if (encoding == TWOS_COMPLEMENT) {
-
3789  int flatInd = 0;
-
3790  for (int r=0; r<numRegs; r++) {
-
3791  phaseInds[r*stride+offset] = 0LL;
-
3792  for (int q=0; q<numQubitsPerReg[r]-1; q++)
-
3793  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
3794  // use final qubit to indicate sign
-
3795  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
3796  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
-
3797  }
-
3798  }
-
3799 
-
3800  // determine if this phase index has an overriden value (i < numOverrides)
-
3801  int i;
-
3802  for (i=0; i<numOverrides; i++) {
-
3803  int found = 1;
-
3804  for (int r=0; r<numRegs; r++) {
-
3805  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
-
3806  found = 0;
-
3807  break;
-
3808  }
-
3809  }
-
3810  if (found)
-
3811  break;
-
3812  }
-
3813 
-
3814  // compute the phase (unless overriden)
-
3815  qreal phase = 0;
-
3816  if (i < numOverrides)
-
3817  phase = overridePhases[i];
-
3818  else {
-
3819  // compute norm related phases
-
3820  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
-
3821  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
-
3822  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
3823  qreal norm = 0;
-
3824  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
3825  for (int r=0; r<numRegs; r++) {
-
3826  qreal dif = phaseInds[r*stride+offset] - params[2+r];
-
3827  norm += dif*dif;
-
3828  }
-
3829  }
-
3830  else
-
3831  for (int r=0; r<numRegs; r++)
-
3832  norm += phaseInds[r*stride+offset]*phaseInds[r*stride+offset];
-
3833  norm = sqrt(norm);
-
3834 
-
3835  if (phaseFuncName == NORM)
-
3836  phase = norm;
-
3837  else if (phaseFuncName == INVERSE_NORM)
-
3838  phase = (norm == 0.)? params[0] : 1/norm;
-
3839  else if (phaseFuncName == SCALED_NORM)
-
3840  phase = params[0] * norm;
-
3841  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
-
3842  phase = (norm == 0.)? params[1] : params[0] / norm;
-
3843  }
-
3844  // compute product related phases
-
3845  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
-
3846  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
-
3847 
-
3848  qreal prod = 1;
-
3849  for (int r=0; r<numRegs; r++)
-
3850  prod *= phaseInds[r*stride+offset];
-
3851 
-
3852  if (phaseFuncName == PRODUCT)
-
3853  phase = prod;
-
3854  else if (phaseFuncName == INVERSE_PRODUCT)
-
3855  phase = (prod == 0.)? params[0] : 1/prod;
-
3856  else if (phaseFuncName == SCALED_PRODUCT)
-
3857  phase = params[0] * prod;
-
3858  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
-
3859  phase = (prod == 0.)? params[1] : params[0] / prod;
-
3860  }
-
3861  // compute Euclidean distance related phases
-
3862  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
-
3863  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
-
3864  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
3865 
-
3866  qreal dist = 0;
-
3867  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
3868  for (int r=0; r<numRegs; r+=2) {
-
3869  qreal dif = (phaseInds[(r+1)*stride+offset] - phaseInds[r*stride+offset] - params[2+r/2]);
-
3870  dist += dif*dif;
-
3871  }
-
3872  }
-
3873  else
-
3874  for (int r=0; r<numRegs; r+=2) {
-
3875  qreal dif = (phaseInds[(r+1)*stride+offset] - phaseInds[r*stride+offset]);
-
3876  dist += dif*dif;
-
3877  }
-
3878  dist = sqrt(dist);
-
3879 
-
3880  if (phaseFuncName == DISTANCE)
-
3881  phase = dist;
-
3882  else if (phaseFuncName == INVERSE_DISTANCE)
-
3883  phase = (dist == 0.)? params[0] : 1/dist;
-
3884  else if (phaseFuncName == SCALED_DISTANCE)
-
3885  phase = params[0] * dist;
-
3886  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
-
3887  phase = (dist == 0.)? params[1] : params[0] / dist;
-
3888  }
-
3889  }
-
3890 
-
3891 
-
3892  // negate phase to conjugate operator
-
3893  if (conj)
-
3894  phase *= -1;
-
3895 
-
3896  // modify amp to amp * exp(i phase)
-
3897  qreal c = cos(phase);
-
3898  qreal s = sin(phase);
-
3899  qreal re = qureg.deviceStateVec.real[index];
-
3900  qreal im = qureg.deviceStateVec.imag[index];
-
3901 
-
3902  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
3903  qureg.deviceStateVec.real[index] = re*c - im*s;
-
3904  qureg.deviceStateVec.imag[index] = re*s + im*c;
-
3905 }
-
3906 
- -
3908  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
-
3909  enum phaseFunc phaseFuncName, qreal* params, int numParams,
-
3910  long long int* overrideInds, qreal* overridePhases, int numOverrides,
-
3911  int conj
-
3912 ) {
-
3913  // determine size of arrays, for cloning into GPU memory
-
3914  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
-
3915  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
-
3916  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
-
3917  size_t mem_params = numParams * sizeof *params;
-
3918  size_t mem_qubits = 0;
-
3919  for (int r=0; r<numRegs; r++)
-
3920  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
-
3921 
-
3922  // allocate global GPU memory
-
3923  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
-
3924  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
-
3925  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
-
3926  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
-
3927  qreal* d_params = NULL; if (numParams > 0) cudaMalloc(&d_params, mem_params);
-
3928 
-
3929  // copy function args into GPU memory
-
3930  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
-
3931  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
-
3932  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
-
3933  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
-
3934  if (numParams > 0)
-
3935  cudaMemcpy(d_params, params, mem_params, cudaMemcpyHostToDevice);
-
3936 
-
3937  int threadsPerCUDABlock = 128;
-
3938  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
-
3939 
-
3940  // allocate thread-local working space {phaseInds}
-
3941  long long int *d_phaseInds;
-
3942  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
-
3943  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
-
3944 
-
3945  // call kernel
-
3946  statevec_applyParamNamedPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
-
3947  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
-
3948  phaseFuncName, d_params, numParams,
-
3949  d_overrideInds, d_overridePhases, numOverrides,
-
3950  d_phaseInds,
-
3951  conj);
-
3952 
-
3953  // free device memory
-
3954  cudaFree(d_qubits);
-
3955  cudaFree(d_numQubitsPerReg);
-
3956  cudaFree(d_overrideInds);
-
3957  cudaFree(d_overridePhases);
-
3958  cudaFree(d_phaseInds);
-
3959  if (numParams > 0)
-
3960  cudaFree(d_params);
-
3961 }
-
3962 
- -
3964  // init MT random number generator with three keys -- time and pid
-
3965  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
3966  // used by the master process
-
3967 
-
3968  unsigned long int key[2];
-
3969  getQuESTDefaultSeedKey(key);
-
3970  init_by_array(key, 2);
-
3971 }
-
3972 
-
3973 
-
3974 
-
3975 
-
3976 #ifdef __cplusplus
-
3977 }
-
3978 #endif
+
3503 void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal* real, qreal* imag, long long int numElems) {
+
3504 
+
3505  // update both RAM and VRAM, for consistency
+
3506  memcpy(&op.real[startInd], real, numElems * sizeof(qreal));
+
3507  memcpy(&op.imag[startInd], imag, numElems * sizeof(qreal));
+
3508 
+
3509  cudaDeviceSynchronize();
+
3510  cudaMemcpy(
+
3511  op.deviceOperator.real + startInd,
+
3512  real,
+
3513  numElems * sizeof(*(op.deviceOperator.real)),
+
3514  cudaMemcpyHostToDevice);
+
3515  cudaMemcpy(
+
3516  op.deviceOperator.imag + startInd,
+
3517  imag,
+
3518  numElems * sizeof(*(op.deviceOperator.imag)),
+
3519  cudaMemcpyHostToDevice);
+
3520 }
+
3521 
+ +
3523  Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding,
+
3524  qreal* coeffs, qreal* exponents, int numTerms,
+
3525  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
3526  int conj
+
3527 ) {
+
3528  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3529  if (index>=qureg.numAmpsPerChunk) return;
+
3530 
+
3531  // determine global amplitude index (non-distributed, so it's just local index)
+
3532  long long int globalAmpInd = index;
+
3533 
+
3534  // determine phase index of {qubits}
+
3535  long long int phaseInd = 0LL;
+
3536  if (encoding == UNSIGNED) {
+
3537  for (int q=0; q<numQubits; q++)
+
3538  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
3539  }
+
3540  else if (encoding == TWOS_COMPLEMENT) {
+
3541  for (int q=0; q<numQubits-1; q++) // use final qubit to indicate sign
+
3542  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
3543  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
+
3544  phaseInd -= (1LL << (numQubits-1));
+
3545  }
+
3546 
+
3547  // determine if this phase index has an overriden value (i < numOverrides)
+
3548  int i;
+
3549  for (i=0; i<numOverrides; i++)
+
3550  if (phaseInd == overrideInds[i])
+
3551  break;
+
3552 
+
3553  // determine phase from {coeffs}, {exponents} (unless overriden)
+
3554  qreal phase = 0;
+
3555  if (i < numOverrides)
+
3556  phase = overridePhases[i];
+
3557  else
+
3558  for (int t=0; t<numTerms; t++)
+
3559  phase += coeffs[t] * pow(phaseInd, exponents[t]);
+
3560 
+
3561  // negate phase to conjugate operator
+
3562  if (conj)
+
3563  phase *= -1;
+
3564 
+
3565  // modify amp to amp * exp(i phase)
+
3566  qreal c = cos(phase);
+
3567  qreal s = sin(phase);
+
3568  qreal re = qureg.deviceStateVec.real[index];
+
3569  qreal im = qureg.deviceStateVec.imag[index];
+
3570 
+
3571  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
3572  qureg.deviceStateVec.real[index] = re*c - im*s;
+
3573  qureg.deviceStateVec.imag[index] = re*s + im*c;
+
3574 }
+
3575 
+ +
3577  Qureg qureg, int* qubits, int numQubits, enum bitEncoding encoding,
+
3578  qreal* coeffs, qreal* exponents, int numTerms,
+
3579  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
3580  int conj
+
3581  ) {
+
3582  // allocate device space for global list of {qubits}, {coeffs}, {exponents}, {overrideInds} and {overridePhases}
+
3583  int* d_qubits; size_t mem_qubits = numQubits * sizeof *d_qubits;
+
3584  qreal* d_coeffs; size_t mem_terms = numTerms * sizeof *d_coeffs;
+
3585  qreal* d_exponents;
+
3586  long long int* d_overrideInds; size_t mem_inds = numOverrides * sizeof *d_overrideInds;
+
3587  qreal* d_overridePhases; size_t mem_phas = numOverrides * sizeof *d_overridePhases;
+
3588  cudaMalloc(&d_qubits, mem_qubits); cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
3589  cudaMalloc(&d_coeffs, mem_terms); cudaMemcpy(d_coeffs, coeffs, mem_terms, cudaMemcpyHostToDevice);
+
3590  cudaMalloc(&d_exponents, mem_terms); cudaMemcpy(d_exponents, exponents, mem_terms, cudaMemcpyHostToDevice);
+
3591  cudaMalloc(&d_overrideInds, mem_inds); cudaMemcpy(d_overrideInds, overrideInds, mem_inds, cudaMemcpyHostToDevice);
+
3592  cudaMalloc(&d_overridePhases,mem_phas); cudaMemcpy(d_overridePhases, overridePhases, mem_phas, cudaMemcpyHostToDevice);
+
3593 
+
3594  // call kernel
+
3595  int threadsPerCUDABlock = 128;
+
3596  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
+
3597  statevec_applyPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
3598  qureg, d_qubits, numQubits, encoding,
+
3599  d_coeffs, d_exponents, numTerms,
+
3600  d_overrideInds, d_overridePhases, numOverrides,
+
3601  conj);
+
3602 
+
3603  // cleanup device memory
+
3604  cudaFree(d_qubits);
+
3605  cudaFree(d_coeffs);
+
3606  cudaFree(d_exponents);
+
3607  cudaFree(d_overrideInds);
+
3608  cudaFree(d_overridePhases);
+
3609 }
+
3610 
+ +
3612  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
+
3613  qreal* coeffs, qreal* exponents, int* numTermsPerReg,
+
3614  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
3615  long long int *phaseInds,
+
3616  int conj
+
3617 ) {
+
3618  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3619  if (index>=qureg.numAmpsPerChunk) return;
+
3620 
+
3621  // determine global amplitude index (non-distributed, so it's just local index)
+
3622  long long int globalAmpInd = index;
+
3623 
+
3624  /*
+
3625  * each thread needs to write to a local:
+
3626  * long long int phaseInds[numRegs];
+
3627  * but instead has access to shared array phaseInds, with below stride and offset
+
3628  */
+
3629  size_t stride = gridDim.x*blockDim.x;
+
3630  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
+
3631 
+
3632  // determine phase indices
+
3633  int flatInd = 0;
+
3634  if (encoding == UNSIGNED) {
+
3635  for (int r=0; r<numRegs; r++) {
+
3636  phaseInds[r*stride+offset] = 0LL;
+
3637  for (int q=0; q<numQubitsPerReg[r]; q++)
+
3638  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3639  }
+
3640  }
+
3641  else if (encoding == TWOS_COMPLEMENT) {
+
3642  for (int r=0; r<numRegs; r++) {
+
3643  phaseInds[r*stride+offset] = 0LL;
+
3644  for (int q=0; q<numQubitsPerReg[r]-1; q++)
+
3645  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3646  // use final qubit to indicate sign
+
3647  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
3648  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
+
3649  }
+
3650  }
+
3651 
+
3652  // determine if this phase index has an overriden value (i < numOverrides)
+
3653  int i;
+
3654  for (i=0; i<numOverrides; i++) {
+
3655  int found = 1;
+
3656  for (int r=0; r<numRegs; r++) {
+
3657  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
+
3658  found = 0;
+
3659  break;
+
3660  }
+
3661  }
+
3662  if (found)
+
3663  break;
+
3664  }
+
3665 
+
3666  // compute the phase (unless overriden)
+
3667  qreal phase = 0;
+
3668  if (i < numOverrides)
+
3669  phase = overridePhases[i];
+
3670  else {
+
3671  flatInd = 0;
+
3672  for (int r=0; r<numRegs; r++) {
+
3673  for (int t=0; t<numTermsPerReg[r]; t++) {
+
3674  phase += coeffs[flatInd] * pow(phaseInds[r*stride+offset], exponents[flatInd]);
+
3675  flatInd++;
+
3676  }
+
3677  }
+
3678  }
+
3679 
+
3680  // negate phase to conjugate operator
+
3681  if (conj)
+
3682  phase *= -1;
+
3683 
+
3684  // modify amp to amp * exp(i phase)
+
3685  qreal c = cos(phase);
+
3686  qreal s = sin(phase);
+
3687  qreal re = qureg.deviceStateVec.real[index];
+
3688  qreal im = qureg.deviceStateVec.imag[index];
+
3689 
+
3690  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
3691  qureg.deviceStateVec.real[index] = re*c - im*s;
+
3692  qureg.deviceStateVec.imag[index] = re*s + im*c;
+
3693 }
+
3694 
+ +
3696  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
+
3697  qreal* coeffs, qreal* exponents, int* numTermsPerReg,
+
3698  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
3699  int conj
+
3700 ) {
+
3701  // determine size of arrays, for cloning into GPU memory
+
3702  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
+
3703  size_t mem_numTermsPerReg = numRegs * sizeof *numTermsPerReg;
+
3704  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
+
3705  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
+
3706  size_t mem_qubits = 0;
+
3707  size_t mem_coeffs = 0;
+
3708  size_t mem_exponents = 0;
+
3709  for (int r=0; r<numRegs; r++) {
+
3710  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
+
3711  mem_coeffs += numTermsPerReg[r] * sizeof *coeffs;
+
3712  mem_exponents += numTermsPerReg[r] * sizeof *exponents;
+
3713  }
+
3714 
+
3715  // allocate global GPU memory
+
3716  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
+
3717  qreal* d_coeffs; cudaMalloc(&d_coeffs, mem_coeffs);
+
3718  qreal* d_exponents; cudaMalloc(&d_exponents, mem_exponents);
+
3719  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
+
3720  int* d_numTermsPerReg; cudaMalloc(&d_numTermsPerReg, mem_numTermsPerReg);
+
3721  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
+
3722  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
+
3723 
+
3724  // copy function args into GPU memory
+
3725  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
3726  cudaMemcpy(d_coeffs, coeffs, mem_coeffs, cudaMemcpyHostToDevice);
+
3727  cudaMemcpy(d_exponents, exponents, mem_exponents, cudaMemcpyHostToDevice);
+
3728  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
+
3729  cudaMemcpy(d_numTermsPerReg, numTermsPerReg, mem_numTermsPerReg, cudaMemcpyHostToDevice);
+
3730  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
+
3731  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
+
3732 
+
3733  int threadsPerCUDABlock = 128;
+
3734  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
+
3735 
+
3736  // allocate thread-local working space {phaseInds}
+
3737  long long int *d_phaseInds;
+
3738  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
+
3739  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
+
3740 
+
3741  // call kernel
+
3742  statevec_applyMultiVarPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
3743  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
+
3744  d_coeffs, d_exponents, d_numTermsPerReg,
+
3745  d_overrideInds, d_overridePhases, numOverrides,
+
3746  d_phaseInds,
+
3747  conj);
+
3748 
+
3749  // free device memory
+
3750  cudaFree(d_qubits);
+
3751  cudaFree(d_coeffs);
+
3752  cudaFree(d_exponents);
+
3753  cudaFree(d_numQubitsPerReg);
+
3754  cudaFree(d_numTermsPerReg);
+
3755  cudaFree(d_overrideInds);
+
3756  cudaFree(d_overridePhases);
+
3757  cudaFree(d_phaseInds);
+
3758 }
+
3759 
+ +
3761  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
+
3762  enum phaseFunc phaseFuncName, qreal* params, int numParams,
+
3763  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
3764  long long int* phaseInds,
+
3765  int conj
+
3766 ) {
+
3767  long long int index = blockIdx.x*blockDim.x + threadIdx.x;
+
3768  if (index>=qureg.numAmpsPerChunk) return;
+
3769 
+
3770  // determine global amplitude index (non-distributed, so it's just local index)
+
3771  long long int globalAmpInd = index;
+
3772 
+
3773  /*
+
3774  * each thread needs to write to a local:
+
3775  * long long int phaseInds[numRegs];
+
3776  * but instead has access to shared array phaseInds, with below stride and offset
+
3777  */
+
3778  size_t stride = gridDim.x*blockDim.x;
+
3779  size_t offset = blockIdx.x*blockDim.x + threadIdx.x;
+
3780 
+
3781  // determine phase indices
+
3782  if (encoding == UNSIGNED) {
+
3783  int flatInd = 0;
+
3784  for (int r=0; r<numRegs; r++) {
+
3785  phaseInds[r*stride+offset] = 0LL;
+
3786  for (int q=0; q<numQubitsPerReg[r]; q++)
+
3787  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3788  }
+
3789  }
+
3790  else if (encoding == TWOS_COMPLEMENT) {
+
3791  int flatInd = 0;
+
3792  for (int r=0; r<numRegs; r++) {
+
3793  phaseInds[r*stride+offset] = 0LL;
+
3794  for (int q=0; q<numQubitsPerReg[r]-1; q++)
+
3795  phaseInds[r*stride+offset] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
3796  // use final qubit to indicate sign
+
3797  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
3798  phaseInds[r*stride+offset] -= (1LL << (numQubitsPerReg[r]-1));
+
3799  }
+
3800  }
+
3801 
+
3802  // determine if this phase index has an overriden value (i < numOverrides)
+
3803  int i;
+
3804  for (i=0; i<numOverrides; i++) {
+
3805  int found = 1;
+
3806  for (int r=0; r<numRegs; r++) {
+
3807  if (phaseInds[r*stride+offset] != overrideInds[i*numRegs+r]) {
+
3808  found = 0;
+
3809  break;
+
3810  }
+
3811  }
+
3812  if (found)
+
3813  break;
+
3814  }
+
3815 
+
3816  // compute the phase (unless overriden)
+
3817  qreal phase = 0;
+
3818  if (i < numOverrides)
+
3819  phase = overridePhases[i];
+
3820  else {
+
3821  // compute norm related phases
+
3822  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
+
3823  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
+
3824  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
3825  qreal norm = 0;
+
3826  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
3827  for (int r=0; r<numRegs; r++) {
+
3828  qreal dif = phaseInds[r*stride+offset] - params[2+r];
+
3829  norm += dif*dif;
+
3830  }
+
3831  }
+
3832  else
+
3833  for (int r=0; r<numRegs; r++)
+
3834  norm += phaseInds[r*stride+offset]*phaseInds[r*stride+offset];
+
3835  norm = sqrt(norm);
+
3836 
+
3837  if (phaseFuncName == NORM)
+
3838  phase = norm;
+
3839  else if (phaseFuncName == INVERSE_NORM)
+
3840  phase = (norm == 0.)? params[0] : 1/norm; // smallest non-zero norm is 1
+
3841  else if (phaseFuncName == SCALED_NORM)
+
3842  phase = params[0] * norm;
+
3843  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
+
3844  phase = (norm <= REAL_EPS)? params[1] : params[0] / norm; // unless shifted closer to zero
+
3845  }
+
3846  // compute product related phases
+
3847  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
+
3848  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
+
3849 
+
3850  qreal prod = 1;
+
3851  for (int r=0; r<numRegs; r++)
+
3852  prod *= phaseInds[r*stride+offset];
+
3853 
+
3854  if (phaseFuncName == PRODUCT)
+
3855  phase = prod;
+
3856  else if (phaseFuncName == INVERSE_PRODUCT)
+
3857  phase = (prod == 0.)? params[0] : 1/prod; // smallest non-zero prod is +- 1
+
3858  else if (phaseFuncName == SCALED_PRODUCT)
+
3859  phase = params[0] * prod;
+
3860  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
+
3861  phase = (prod == 0.)? params[1] : params[0] / prod;
+
3862  }
+
3863  // compute Euclidean distance related phases
+
3864  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
+
3865  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
+
3866  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
3867 
+
3868  qreal dist = 0;
+
3869  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
3870  for (int r=0; r<numRegs; r+=2) {
+
3871  qreal dif = (phaseInds[r*stride+offset] - phaseInds[(r+1)*stride+offset] - params[2+r/2]);
+
3872  dist += dif*dif;
+
3873  }
+
3874  }
+
3875  else
+
3876  for (int r=0; r<numRegs; r+=2) {
+
3877  qreal dif = (phaseInds[(r+1)*stride+offset] - phaseInds[r*stride+offset]);
+
3878  dist += dif*dif;
+
3879  }
+
3880  dist = sqrt(dist);
+
3881 
+
3882  if (phaseFuncName == DISTANCE)
+
3883  phase = dist;
+
3884  else if (phaseFuncName == INVERSE_DISTANCE)
+
3885  phase = (dist == 0.)? params[0] : 1/dist; // smallest non-zero dist is 1
+
3886  else if (phaseFuncName == SCALED_DISTANCE)
+
3887  phase = params[0] * dist;
+
3888  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
+
3889  phase = (dist <= REAL_EPS)? params[1] : params[0] / dist; // unless shifted closer
+
3890  }
+
3891  }
+
3892 
+
3893 
+
3894  // negate phase to conjugate operator
+
3895  if (conj)
+
3896  phase *= -1;
+
3897 
+
3898  // modify amp to amp * exp(i phase)
+
3899  qreal c = cos(phase);
+
3900  qreal s = sin(phase);
+
3901  qreal re = qureg.deviceStateVec.real[index];
+
3902  qreal im = qureg.deviceStateVec.imag[index];
+
3903 
+
3904  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
3905  qureg.deviceStateVec.real[index] = re*c - im*s;
+
3906  qureg.deviceStateVec.imag[index] = re*s + im*c;
+
3907 }
+
3908 
+ +
3910  Qureg qureg, int* qubits, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding,
+
3911  enum phaseFunc phaseFuncName, qreal* params, int numParams,
+
3912  long long int* overrideInds, qreal* overridePhases, int numOverrides,
+
3913  int conj
+
3914 ) {
+
3915  // determine size of arrays, for cloning into GPU memory
+
3916  size_t mem_numQubitsPerReg = numRegs * sizeof *numQubitsPerReg;
+
3917  size_t mem_overridePhases = numOverrides * sizeof *overridePhases;
+
3918  size_t mem_overrideInds = numOverrides * numRegs * sizeof *overrideInds;
+
3919  size_t mem_params = numParams * sizeof *params;
+
3920  size_t mem_qubits = 0;
+
3921  for (int r=0; r<numRegs; r++)
+
3922  mem_qubits += numQubitsPerReg[r] * sizeof *qubits;
+
3923 
+
3924  // allocate global GPU memory
+
3925  int* d_qubits; cudaMalloc(&d_qubits, mem_qubits);
+
3926  int* d_numQubitsPerReg; cudaMalloc(&d_numQubitsPerReg, mem_numQubitsPerReg);
+
3927  long long int* d_overrideInds; cudaMalloc(&d_overrideInds, mem_overrideInds);
+
3928  qreal* d_overridePhases; cudaMalloc(&d_overridePhases, mem_overridePhases);
+
3929  qreal* d_params = NULL; if (numParams > 0) cudaMalloc(&d_params, mem_params);
+
3930 
+
3931  // copy function args into GPU memory
+
3932  cudaMemcpy(d_qubits, qubits, mem_qubits, cudaMemcpyHostToDevice);
+
3933  cudaMemcpy(d_numQubitsPerReg, numQubitsPerReg, mem_numQubitsPerReg, cudaMemcpyHostToDevice);
+
3934  cudaMemcpy(d_overrideInds, overrideInds, mem_overrideInds, cudaMemcpyHostToDevice);
+
3935  cudaMemcpy(d_overridePhases, overridePhases, mem_overridePhases, cudaMemcpyHostToDevice);
+
3936  if (numParams > 0)
+
3937  cudaMemcpy(d_params, params, mem_params, cudaMemcpyHostToDevice);
+
3938 
+
3939  int threadsPerCUDABlock = 128;
+
3940  int CUDABlocks = ceil((qreal) qureg.numAmpsPerChunk / threadsPerCUDABlock);
+
3941 
+
3942  // allocate thread-local working space {phaseInds}
+
3943  long long int *d_phaseInds;
+
3944  size_t gridSize = (size_t) threadsPerCUDABlock * CUDABlocks;
+
3945  cudaMalloc(&d_phaseInds, numRegs*gridSize * sizeof *d_phaseInds);
+
3946 
+
3947  // call kernel
+
3948  statevec_applyParamNamedPhaseFuncOverridesKernel<<<CUDABlocks,threadsPerCUDABlock>>>(
+
3949  qureg, d_qubits, d_numQubitsPerReg, numRegs, encoding,
+
3950  phaseFuncName, d_params, numParams,
+
3951  d_overrideInds, d_overridePhases, numOverrides,
+
3952  d_phaseInds,
+
3953  conj);
+
3954 
+
3955  // free device memory
+
3956  cudaFree(d_qubits);
+
3957  cudaFree(d_numQubitsPerReg);
+
3958  cudaFree(d_overrideInds);
+
3959  cudaFree(d_overridePhases);
+
3960  cudaFree(d_phaseInds);
+
3961  if (numParams > 0)
+
3962  cudaFree(d_params);
+
3963 }
+
3964 
+
3965 void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds) {
+
3966 
+
3967  // free existing seed array, if exists
+
3968  if (env->seeds != NULL)
+
3969  free(env->seeds);
+
3970 
+
3971  // record keys in permanent heap
+
3972  env->seeds = malloc(numSeeds * sizeof *(env->seeds));
+
3973  for (int i=0; i<numSeeds; i++)
+
3974  (env->seeds)[i] = seedArray[i];
+
3975  env->numSeeds = numSeeds;
+
3976 
+
3977  // pass keys to Mersenne Twister seeder
+
3978  init_by_array(seedArray, numSeeds);
+
3979 }
+
3980 
+
3981 
+
3982 
+
3983 #ifdef __cplusplus
+
3984 }
+
3985 #endif
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_gpu.cu:418
@ INVERSE_PRODUCT
Definition: QuEST.h:233
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_gpu.cu:3046
-
__global__ void statevec_multiControlledUnitaryKernel(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:1243
-
__global__ void statevec_initPlusStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:629
-
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
Definition: QuEST_gpu.cu:487
+
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_gpu.cu:3048
+
__global__ void statevec_multiControlledUnitaryKernel(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:1245
+
__global__ void statevec_initPlusStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:631
+
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
Definition: QuEST_gpu.cu:489
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
__device__ __host__ unsigned int log2Int(unsigned int x)
Definition: QuEST_gpu.cu:1923
+
__device__ __host__ unsigned int log2Int(unsigned int x)
Definition: QuEST_gpu.cu:1925
__global__ void agnostic_initDiagonalOpFromPauliHamilKernel(DiagonalOp op, enum pauliOpType *pauliCodes, qreal *termCoeffs, int numSumTerms)
Definition: QuEST_gpu.cu:389
-
__global__ void statevec_setWeightedQuregKernel(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_gpu.cu:3141
-
__global__ void densmatr_collapseToKnownProbOutcomeKernel(qreal outcomeProb, qreal *vecReal, qreal *vecImag, long long int numBasesToVisit, long long int part1, long long int part2, long long int part3, long long int rowBit, long long int colBit, long long int desired, long long int undesired)
Maps thread ID to a |..0..><..0..| state and then locates |0><1|, |1><0| and |1><1|.
Definition: QuEST_gpu.cu:2777
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
Definition: QuEST_gpu.cu:1767
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_gpu.cu:527
-
__global__ void statevec_controlledUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:1177
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_gpu.cu:1586
+
__global__ void statevec_setWeightedQuregKernel(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_gpu.cu:3143
+
__global__ void densmatr_collapseToKnownProbOutcomeKernel(qreal outcomeProb, qreal *vecReal, qreal *vecImag, long long int numBasesToVisit, long long int part1, long long int part2, long long int part3, long long int rowBit, long long int colBit, long long int desired, long long int undesired)
Maps thread ID to a |..0..><..0..| state and then locates |0><1|, |1><0| and |1><1|.
Definition: QuEST_gpu.cu:2779
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
Definition: QuEST_gpu.cu:1769
+
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_gpu.cu:529
+
__global__ void statevec_controlledUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:1179
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_gpu.cu:1588
qreal real[4][4]
Definition: QuEST.h:177
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
Definition: QuEST_gpu.cu:479
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
Definition: QuEST_gpu.cu:481
__global__ void densmatr_initPureStateKernel(long long int numPureAmps, qreal *targetVecReal, qreal *targetVecImag, qreal *copyVecReal, qreal *copyVecImag)
Definition: QuEST_gpu.cu:186
@ PAULI_Z
Definition: QuEST.h:96
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_gpu.cu:153
-
__global__ void densmatr_mixTwoQubitDepolarisingKernel(qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int rowCol1, long long int rowCol2)
Called once for every 16 amplitudes.
Definition: QuEST_gpu.cu:3074
+
__global__ void densmatr_mixTwoQubitDepolarisingKernel(qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int rowCol1, long long int rowCol2)
Called once for every 16 amplitudes.
Definition: QuEST_gpu.cu:3076
@ DISTANCE
Definition: QuEST.h:234
-
int rank
Definition: QuEST.h:363
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_gpu.cu:1556
+
int rank
Definition: QuEST.h:364
+
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_gpu.cu:1558
int GPUExists(void)
Definition: QuEST_gpu.cu:446
-
__global__ void copySharedReduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1949
-
void swapDouble(qreal **a, qreal **b)
Definition: QuEST_gpu.cu:2055
-
__global__ void statevec_applyPhaseFuncOverridesKernel(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3520
-
__global__ void statevec_multiControlledMultiQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, qreal *uRe, qreal *uIm, long long int *ampInds, qreal *reAmps, qreal *imAmps, long long int numTargAmps)
Definition: QuEST_gpu.cu:978
+
__global__ void copySharedReduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1951
+
void swapDouble(qreal **a, qreal **b)
Definition: QuEST_gpu.cu:2057
+
void seedQuESTDefault(QuESTEnv *env)
Seeds the random number generator with the (master node) current time and process ID.
Definition: QuEST.c:1614
+
__global__ void statevec_applyPhaseFuncOverridesKernel(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3522
+
__global__ void statevec_multiControlledMultiQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, qreal *uRe, qreal *uIm, long long int *ampInds, qreal *reAmps, qreal *imAmps, long long int numTargAmps)
Definition: QuEST_gpu.cu:980
__global__ void densmatr_initClassicalStateKernel(long long int densityNumElems, qreal *densityReal, qreal *densityImag, long long int densityInd)
Definition: QuEST_gpu.cu:239
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_gpu.cu:725
+
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_gpu.cu:727
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:304
-
void statevec_pauliY(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1391
+
void statevec_pauliY(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1393
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
-
qreal statevec_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2110
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:909
+
qreal statevec_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2112
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:911
-
__global__ void densmatr_calcExpecDiagonalOpKernel(int getRealComp, qreal *matReal, qreal *matImag, qreal *opReal, qreal *opImag, int numQubits, long long int numTermsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:3365
+
__global__ void densmatr_calcExpecDiagonalOpKernel(int getRealComp, qreal *matReal, qreal *matImag, qreal *opReal, qreal *opImag, int numQubits, long long int numTermsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:3367
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_gpu.cu:382
-
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
Definition: QuEST_gpu.cu:503
-
__global__ void statevec_controlledPhaseShiftKernel(Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1500
+
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
Definition: QuEST_gpu.cu:505
+
__global__ void statevec_controlledPhaseShiftKernel(Qureg qureg, int idQubit1, int idQubit2, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1502
#define DEBUG
Definition: QuEST_gpu.cu:20
+
int numSeeds
Definition: QuEST.h:367
-
__global__ void statevec_multiRotateZKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1569
+
__global__ void statevec_multiRotateZKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1571
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
-
__global__ void densmatr_applyDiagonalOpKernel(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3215
-
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
+
__global__ void densmatr_applyDiagonalOpKernel(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3217
ComplexArray deviceOperator
A copy of the elements stored persistently on the GPU.
Definition: QuEST.h:312
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Definition: QuEST_gpu.cu:1170
-
__global__ void densmatr_calcHilbertSchmidtDistanceSquaredKernel(qreal *aRe, qreal *aIm, qreal *bRe, qreal *bIm, long long int numAmpsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:2567
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_gpu.cu:1706
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Definition: QuEST_gpu.cu:1172
+
__global__ void densmatr_calcHilbertSchmidtDistanceSquaredKernel(qreal *aRe, qreal *aIm, qreal *bRe, qreal *bIm, long long int numAmpsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:2569
+
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_gpu.cu:1708
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:306
ComplexArray deviceStateVec
Storage for wavefunction amplitudes in the GPU version.
Definition: QuEST.h:346
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
Definition: QuEST_gpu.cu:567
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
Definition: QuEST_gpu.cu:569
@ NORM
Definition: QuEST.h:232
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_gpu.cu:275
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
Definition: QuEST_gpu.cu:2311
-
__global__ void densmatr_mixDampingKernel(qreal damping, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
Works like mixDephasing but modifies every other element, and elements are averaged in pairs.
Definition: QuEST_gpu.cu:2999
-
void statevec_hadamard(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1824
-
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3693
-
__global__ void statevec_calcExpecDiagonalOpKernel(int getRealComp, qreal *vecReal, qreal *vecImag, qreal *opReal, qreal *opImag, long long int numTermsToSum, qreal *reducedArray)
computes either a real or imag term of |vec_i|^2 op_i
Definition: QuEST_gpu.cu:3247
+
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
Definition: QuEST_gpu.cu:2313
+
__global__ void densmatr_mixDampingKernel(qreal damping, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
Works like mixDephasing but modifies every other element, and elements are averaged in pairs.
Definition: QuEST_gpu.cu:3001
+
void statevec_hadamard(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1826
+
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3695
+
__global__ void statevec_calcExpecDiagonalOpKernel(int getRealComp, qreal *vecReal, qreal *vecImag, qreal *opReal, qreal *opImag, long long int numTermsToSum, qreal *reducedArray)
computes either a real or imag term of |vec_i|^2 op_i
Definition: QuEST_gpu.cu:3249
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac)
Definition: QuEST_gpu.cu:2877
+
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal dephFac)
Definition: QuEST_gpu.cu:2879
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
-
__global__ void densmatr_mixTwoQubitDephasingKernel(qreal fac, qreal *vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
Called 12 times for every 16 amplitudes in density matrix Each sums from the |..0....
Definition: QuEST_gpu.cu:2912
-
Information about the environment the program is running in.
Definition: QuEST.h:361
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_gpu.cu:666
+
__global__ void densmatr_mixTwoQubitDephasingKernel(qreal fac, qreal *vecReal, qreal *vecImag, long long int numBackgroundStates, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int part4, long long int part5, long long int colBit1, long long int rowBit1, long long int colBit2, long long int rowBit2)
Called 12 times for every 16 amplitudes in density matrix Each sums from the |..0....
Definition: QuEST_gpu.cu:2914
+
Information about the environment the program is running in.
Definition: QuEST.h:362
+
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_gpu.cu:668
@ UNSIGNED
Definition: QuEST.h:269
-
void densmatr_calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2257
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Definition: QuEST_gpu.cu:1037
+
void densmatr_calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2259
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Definition: QuEST_gpu.cu:1039
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
@ INVERSE_DISTANCE
Definition: QuEST.h:234
-
qreal densmatr_calcTotalProb(Qureg qureg)
Definition: QuEST_gpu.cu:1630
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_gpu.cu:1732
-
__global__ void statevec_controlledCompactUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:850
+
qreal densmatr_calcTotalProb(Qureg qureg)
Definition: QuEST_gpu.cu:1632
+
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_gpu.cu:1734
+
__global__ void statevec_controlledCompactUnitaryKernel(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:852
#define qreal
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:970
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Definition: QuEST_gpu.cu:2768
-
void statevec_pauliX(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1358
+
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:972
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Definition: QuEST_gpu.cu:2770
+
void statevec_pauliX(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1360
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_gpu.cu:258
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
__global__ void statevec_unitaryKernel(Qureg qureg, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:917
-
__global__ void statevec_multiControlledPhaseFlipKernel(Qureg qureg, long long int mask)
Definition: QuEST_gpu.cu:1714
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_gpu.cu:618
-
__global__ void statevec_findProbabilityOfZeroKernel(Qureg qureg, int measureQubit, qreal *reducedArray)
Definition: QuEST_gpu.cu:1996
-
__global__ void statevec_applyDiagonalOpKernel(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3185
+
__global__ void statevec_unitaryKernel(Qureg qureg, int targetQubit, ArgMatrix2 u)
Definition: QuEST_gpu.cu:919
+
__global__ void statevec_multiControlledPhaseFlipKernel(Qureg qureg, long long int mask)
Definition: QuEST_gpu.cu:1716
+
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_gpu.cu:620
+
__global__ void statevec_findProbabilityOfZeroKernel(Qureg qureg, int measureQubit, qreal *reducedArray)
Definition: QuEST_gpu.cu:1998
+
__global__ void statevec_applyDiagonalOpKernel(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3187
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
-
__global__ void statevec_initBlankStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:581
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Definition: QuEST_gpu.cu:2148
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_gpu.cu:1619
-
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3574
-
qreal statevec_calcTotalProb(Qureg qureg)
Definition: QuEST_gpu.cu:1653
-
__global__ void densmatr_calcInnerProductKernel(Qureg a, Qureg b, long long int numTermsToSum, qreal *reducedArray)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij), which is a real number
Definition: QuEST_gpu.cu:2290
+
__global__ void statevec_initBlankStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:583
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Definition: QuEST_gpu.cu:2150
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_gpu.cu:1621
+
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3576
+
qreal statevec_calcTotalProb(Qureg qureg)
Definition: QuEST_gpu.cu:1655
+
__global__ void densmatr_calcInnerProductKernel(Qureg a, Qureg b, long long int numTermsToSum, qreal *reducedArray)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij), which is a real number
Definition: QuEST_gpu.cu:2292
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_gpu.cu:1489
+
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_gpu.cu:1491
qreal imag[2][2]
Definition: QuEST.h:140
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_gpu.cu:769
+
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_gpu.cu:771
__forceinline__ __device__ long long int insertZeroBit(const long long int number, const int index)
Definition: QuEST_gpu.cu:99
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_gpu.cu:2844
-
qreal densmatr_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2062
+
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_gpu.cu:2846
+
qreal densmatr_findProbabilityOfZero(Qureg qureg, int measureQubit)
Definition: QuEST_gpu.cu:2064
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
-
__global__ void statevec_pauliXKernel(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1314
+
__global__ void statevec_pauliXKernel(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1316
__forceinline__ __device__ int getBitMaskParity(long long int mask)
Definition: QuEST_gpu.cu:86
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3207
+
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3209
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_gpu.cu:205
-
__global__ void statevec_multiControlledMultiQubitNotKernel(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_gpu.cu:1879
-
__global__ void statevec_phaseShiftByTermKernel(Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1461
-
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_gpu.cu:1916
+
__global__ void statevec_multiControlledMultiQubitNotKernel(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_gpu.cu:1881
+
__global__ void statevec_phaseShiftByTermKernel(Qureg qureg, int targetQubit, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1463
+
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_gpu.cu:1918
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
__global__ void statevec_initZeroStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:602
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_gpu.cu:517
+
__global__ void statevec_initZeroStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:604
+
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_gpu.cu:519
#define REDUCE_SHARED_SIZE
Definition: QuEST_gpu.cu:19
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
__global__ void densmatr_calcPurityKernel(qreal *vecReal, qreal *vecImag, long long int numAmpsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:2643
+
__global__ void densmatr_calcPurityKernel(qreal *vecReal, qreal *vecImag, long long int numAmpsToSum, qreal *reducedArray)
Definition: QuEST_gpu.cu:2645
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_gpu.cu:338
-
void statevec_calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2205
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc phaseFuncName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3907
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
Definition: QuEST_gpu.cu:574
-
int numRanks
Definition: QuEST.h:364
+
void statevec_calcProbOfAllOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2207
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc phaseFuncName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_gpu.cu:3909
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
Definition: QuEST_gpu.cu:576
+
int numRanks
Definition: QuEST.h:365
qreal imag[4][4]
Definition: QuEST.h:178
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Definition: QuEST_gpu.cu:2156
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:842
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
Definition: QuEST_gpu.cu:2158
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:844
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
__forceinline__ __device__ long long int insertZeroBits(long long int number, int *inds, const int numInds)
Definition: QuEST_gpu.cu:112
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3410
-
__global__ void densmatr_mixDephasingKernel(qreal fac, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int colBit, long long int rowBit)
Called once for every 4 amplitudes in density matrix Works by establishing the |.....
Definition: QuEST_gpu.cu:2861
+
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3412
+
__global__ void densmatr_mixDephasingKernel(qreal fac, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int colBit, long long int rowBit)
Called once for every 4 amplitudes in density matrix Works by establishing the |.....
Definition: QuEST_gpu.cu:2863
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
-
int getNumReductionLevels(long long int numValuesToReduce, int numReducedPerLevel)
Definition: QuEST_gpu.cu:2046
-
__global__ void statevec_multiControlledMultiRotateZKernel(Qureg qureg, long long int ctrlMask, long long int targMask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1597
+
int getNumReductionLevels(long long int numValuesToReduce, int numReducedPerLevel)
Definition: QuEST_gpu.cu:2048
+
__global__ void statevec_multiControlledMultiRotateZKernel(Qureg qureg, long long int ctrlMask, long long int targMask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1599
qreal ** real
Definition: QuEST.h:189
-
__global__ void statevec_hadamardKernel(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1775
-
__global__ void statevec_controlledPhaseFlipKernel(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_gpu.cu:1685
+
__global__ void statevec_hadamardKernel(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1777
+
__global__ void statevec_controlledPhaseFlipKernel(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_gpu.cu:1687
qreal * secondLevelReduction
Definition: QuEST.h:348
__global__ void densmatr_initPlusStateKernel(long long int stateVecSize, qreal probFactor, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:216
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
-
__global__ void densmatr_mixDepolarisingKernel(qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
Works like mixDephasing but modifies every other element, and elements are averaged in pairs.
Definition: QuEST_gpu.cu:2973
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
Definition: QuEST_gpu.cu:3106
-
__global__ void statevec_calcProbOfAllOutcomesKernel(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2184
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_gpu.cu:1525
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
Definition: QuEST_gpu.cu:2591
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_gpu.cu:2936
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_gpu.cu:591
+
__global__ void densmatr_mixDepolarisingKernel(qreal depolLevel, qreal *vecReal, qreal *vecImag, long long int numAmpsToVisit, long long int part1, long long int part2, long long int part3, long long int bothBits)
Works like mixDephasing but modifies every other element, and elements are averaged in pairs.
Definition: QuEST_gpu.cu:2975
+
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
Definition: QuEST_gpu.cu:3108
+
unsigned long int * seeds
Definition: QuEST.h:366
+
__global__ void statevec_calcProbOfAllOutcomesKernel(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2186
+
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_gpu.cu:1527
+
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
Definition: QuEST_gpu.cu:2593
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_gpu.cu:2938
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_gpu.cu:593
@ INVERSE_NORM
Definition: QuEST.h:232
Represents a system of qubits.
Definition: QuEST.h:322
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1443
-
__global__ void statevec_initDebugStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:677
+
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1445
+
__global__ void statevec_initDebugStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag)
Definition: QuEST_gpu.cu:679
__forceinline__ __device__ long long int insertTwoZeroBits(const long long int number, const int bit1, const int bit2)
Definition: QuEST_gpu.cu:106
-
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
Definition: QuEST_gpu.cu:2391
+
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
Definition: QuEST_gpu.cu:2393
qreal ** imag
Definition: QuEST.h:190
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
This involves finding |...i...><...j...| states and killing those where i!=j.
Definition: QuEST_gpu.cu:2803
-
__global__ void statevec_pauliYKernel(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_gpu.cu:1366
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_gpu.cu:541
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
This involves finding |...i...><...j...| states and killing those where i!=j.
Definition: QuEST_gpu.cu:2805
+
__global__ void statevec_pauliYKernel(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_gpu.cu:1368
+
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_gpu.cu:543
@ PRODUCT
Definition: QuEST.h:233
-
__global__ void statevec_initClassicalStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd)
Definition: QuEST_gpu.cu:651
+
__global__ void statevec_initClassicalStateKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, long long int stateInd)
Definition: QuEST_gpu.cu:653
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
-
__global__ void statevec_calcInnerProductKernel(int getRealComp, qreal *vecReal1, qreal *vecImag1, qreal *vecReal2, qreal *vecImag2, long long int numTermsToSum, qreal *reducedArray)
computes either a real or imag term in the inner product
Definition: QuEST_gpu.cu:2361
-
__global__ void densmatr_findProbabilityOfZeroKernel(Qureg qureg, int measureQubit, qreal *reducedArray)
Definition: QuEST_gpu.cu:1958
+
__global__ void statevec_calcInnerProductKernel(int getRealComp, qreal *vecReal1, qreal *vecImag1, qreal *vecReal2, qreal *vecImag2, long long int numTermsToSum, qreal *reducedArray)
computes either a real or imag term in the inner product
Definition: QuEST_gpu.cu:2363
+
__global__ void densmatr_findProbabilityOfZeroKernel(Qureg qureg, int measureQubit, qreal *reducedArray)
Definition: QuEST_gpu.cu:1960
qreal real[2][2]
Definition: QuEST.h:139
-
__global__ void statevec_applyParamNamedPhaseFuncOverridesKernel(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc phaseFuncName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, long long int *phaseInds, int conj)
Definition: QuEST_gpu.cu:3758
-
void seedQuESTDefault()
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
Definition: QuEST_gpu.cu:3963
+
__global__ void statevec_applyParamNamedPhaseFuncOverridesKernel(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc phaseFuncName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, long long int *phaseInds, int conj)
Definition: QuEST_gpu.cu:3760
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
__global__ void statevec_controlledPauliYKernel(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_gpu.cu:1407
-
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
Definition: QuEST_gpu.cu:491
+
__global__ void statevec_controlledPauliYKernel(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_gpu.cu:1409
+
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
Definition: QuEST_gpu.cu:493
int numQubits
Definition: QuEST.h:188
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_gpu.cu:2897
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:1235
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_gpu.cu:2899
+
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:1237
void densmatr_initPlusState(Qureg qureg)
Definition: QuEST_gpu.cu:226
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1399
+
void statevec_pauliYConj(Qureg qureg, int targetQubit)
Definition: QuEST_gpu.cu:1401
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_gpu.cu:321
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1871
+
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1873
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_gpu.cu:170
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_gpu.cu:375
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
-
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
Definition: QuEST_gpu.cu:483
+
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
Definition: QuEST_gpu.cu:485
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
__device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1930
+
__device__ void reduceBlock(qreal *arrayIn, qreal *reducedArray, int length)
Definition: QuEST_gpu.cu:1932
qreal imag
Definition: QuEST.h:106
-
__global__ void statevec_initStateOfSingleQubitKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome)
Definition: QuEST_gpu.cu:698
-
__global__ void statevec_collapseToKnownProbOutcomeKernel(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Definition: QuEST_gpu.cu:2711
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3238
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_gpu.cu:687
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:1303
-
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
Definition: QuEST_gpu.cu:2662
-
__global__ void statevec_multiControlledTwoQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u)
Definition: QuEST_gpu.cu:1094
+
__global__ void statevec_initStateOfSingleQubitKernel(long long int stateVecSize, qreal *stateVecReal, qreal *stateVecImag, int qubitId, int outcome)
Definition: QuEST_gpu.cu:700
+
__global__ void statevec_collapseToKnownProbOutcomeKernel(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Definition: QuEST_gpu.cu:2713
+
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3240
+
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_gpu.cu:689
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_gpu.cu:1305
+
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
Definition: QuEST_gpu.cu:2664
+
__global__ void statevec_multiControlledTwoQubitUnitaryKernel(Qureg qureg, long long int ctrlMask, int q1, int q2, ArgMatrix4 u)
Definition: QuEST_gpu.cu:1096
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
+
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
Definition: QuEST_gpu.cu:3965
Represents one complex number.
Definition: QuEST.h:103
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
Definition: QuEST_gpu.cu:463
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_gpu.cu:716
+
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_gpu.cu:718
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_gpu.cu:3173
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_gpu.cu:2517
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_gpu.cu:640
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_gpu.cu:3175
+
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_gpu.cu:2519
+
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_gpu.cu:642
qreal * firstLevelReduction
Storage for reduction of probabilities on GPU.
Definition: QuEST.h:348
-
__global__ void statevec_compactUnitaryKernel(Qureg qureg, int rotQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:787
-
__global__ void statevec_applyMultiVarPhaseFuncOverridesKernel(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, long long int *phaseInds, int conj)
Definition: QuEST_gpu.cu:3609
-
__global__ void statevec_controlledNotKernel(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1832
-
__global__ void densmatr_calcProbOfAllOutcomesKernel(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2236
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3274
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_gpu.cu:3501
-
__global__ void densmatr_mixDensityMatrixKernel(Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit)
Definition: QuEST_gpu.cu:2832
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_gpu.cu:3020
+
__global__ void statevec_compactUnitaryKernel(Qureg qureg, int rotQubit, Complex alpha, Complex beta)
Definition: QuEST_gpu.cu:789
+
__global__ void statevec_applyMultiVarPhaseFuncOverridesKernel(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, long long int *phaseInds, int conj)
Definition: QuEST_gpu.cu:3611
+
__global__ void statevec_controlledNotKernel(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1834
+
__global__ void densmatr_calcProbOfAllOutcomesKernel(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_gpu.cu:2238
+
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_gpu.cu:3276
+
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_gpu.cu:3503
+
__global__ void densmatr_mixDensityMatrixKernel(Qureg combineQureg, qreal otherProb, Qureg otherQureg, long long int numAmpsToVisit)
Definition: QuEST_gpu.cu:2834
+
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_gpu.cu:3022
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
__global__ void statevec_swapQubitAmpsKernel(Qureg qureg, int qb1, int qb2)
Definition: QuEST_gpu.cu:1741
+
__global__ void statevec_swapQubitAmpsKernel(Qureg qureg, int qb1, int qb2)
Definition: QuEST_gpu.cu:1743
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1452
-
__global__ void densmatr_calcFidelityKernel(Qureg dens, Qureg vec, long long int dim, qreal *reducedArray)
computes one term of (vec^*T) dens * vec
Definition: QuEST_gpu.cu:2479
+
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_gpu.cu:1454
+
__global__ void densmatr_calcFidelityKernel(Qureg dens, Qureg vec, long long int dim, qreal *reducedArray)
computes one term of (vec^*T) dens * vec
Definition: QuEST_gpu.cu:2481
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
-
__global__ void statevec_multiControlledPhaseShiftKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1536
+
__global__ void statevec_multiControlledPhaseShiftKernel(Qureg qureg, long long int mask, qreal cosAngle, qreal sinAngle)
Definition: QuEST_gpu.cu:1538
diff --git a/docs/QuEST__internal_8h.html b/docs/QuEST__internal_8h.html index 6624c0364..5dc9af2f1 100644 --- a/docs/QuEST__internal_8h.html +++ b/docs/QuEST__internal_8h.html @@ -27,7 +27,7 @@ @@ -372,74 +372,74 @@

-

Definition at line 836 of file QuEST_common.c.

-
836  {
-
837 
-
838  int densShift = qureg.numQubitsRepresented;
-
839 
-
840  // start with top/left-most qubit, work down
-
841  for (int q=numQubits-1; q >= 0; q--) {
-
842 
-
843  // H
-
844  statevec_hadamard(qureg, qubits[q]);
-
845  if (qureg.isDensityMatrix)
-
846  statevec_hadamard(qureg, qubits[q] + densShift);
-
847  qasm_recordGate(qureg, GATE_HADAMARD, qubits[q]);
-
848 
-
849  if (q == 0)
-
850  break;
-
851 
-
852  // succession of C-phases, control on qubits[q], targeting each of
-
853  // qubits[q-1], qubits[q-1], ... qubits[0]. This can be expressed by
-
854  // a single invocation of applyNamedPhaseFunc product
+

Definition at line 849 of file QuEST_common.c.

+
849  {
+
850 
+
851  int densShift = qureg.numQubitsRepresented;
+
852 
+
853  // start with top/left-most qubit, work down
+
854  for (int q=numQubits-1; q >= 0; q--) {
855 
-
856  int numRegs = 2;
-
857  int numQubitsPerReg[2] = {q, 1};
-
858  int regs[q+1];
-
859  for (int i=0; i<q+1; i++)
-
860  regs[i] = qubits[i]; // qubits[q] is in own register
+
856  // H
+
857  statevec_hadamard(qureg, qubits[q]);
+
858  if (qureg.isDensityMatrix)
+
859  statevec_hadamard(qureg, qubits[q] + densShift);
+
860  qasm_recordGate(qureg, GATE_HADAMARD, qubits[q]);
861 
-
862  int numParams = 1;
-
863  qreal params[1] = { M_PI / (1 << q) };
+
862  if (q == 0)
+
863  break;
864 
-
865  int conj = 0;
- -
867  qureg, regs, numQubitsPerReg, numRegs,
-
868  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
869  NULL, NULL, 0,
-
870  conj);
-
871  if (qureg.isDensityMatrix) {
-
872  conj = 1;
-
873  shiftSubregIndices(regs, numQubitsPerReg, numRegs, densShift);
- -
875  qureg, regs, numQubitsPerReg, numRegs,
-
876  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
877  NULL, NULL, 0,
-
878  conj);
-
879  shiftSubregIndices(regs, numQubitsPerReg, numRegs, - densShift);
-
880  }
- -
882  qureg, regs, numQubitsPerReg, numRegs,
-
883  UNSIGNED, SCALED_PRODUCT, params, numParams,
-
884  NULL, NULL, 0);
-
885  }
-
886 
-
887  // final swaps
-
888  for (int i=0; i<(numQubits/2); i++) {
-
889 
-
890  int qb1 = qubits[i];
-
891  int qb2 = qubits[numQubits-i-1];
-
892 
-
893  statevec_swapQubitAmps(qureg, qb1, qb2);
-
894  if (qureg.isDensityMatrix)
-
895  statevec_swapQubitAmps(qureg, qb1 + densShift, qb2 + densShift);
-
896  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
-
897  }
-
898 }
+
865  // succession of C-phases, control on qubits[q], targeting each of
+
866  // qubits[q-1], qubits[q-1], ... qubits[0]. This can be expressed by
+
867  // a single invocation of applyNamedPhaseFunc product
+
868 
+
869  int numRegs = 2;
+
870  int numQubitsPerReg[2] = {q, 1};
+
871  int regs[100]; // [q+1];
+
872  for (int i=0; i<q+1; i++)
+
873  regs[i] = qubits[i]; // qubits[q] is in own register
+
874 
+
875  int numParams = 1;
+
876  qreal params[1] = { M_PI / (1 << q) };
+
877 
+
878  int conj = 0;
+ +
880  qureg, regs, numQubitsPerReg, numRegs,
+
881  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
882  NULL, NULL, 0,
+
883  conj);
+
884  if (qureg.isDensityMatrix) {
+
885  conj = 1;
+
886  shiftSubregIndices(regs, numQubitsPerReg, numRegs, densShift);
+ +
888  qureg, regs, numQubitsPerReg, numRegs,
+
889  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
890  NULL, NULL, 0,
+
891  conj);
+
892  shiftSubregIndices(regs, numQubitsPerReg, numRegs, - densShift);
+
893  }
+ +
895  qureg, regs, numQubitsPerReg, numRegs,
+
896  UNSIGNED, SCALED_PRODUCT, params, numParams,
+
897  NULL, NULL, 0);
+
898  }
+
899 
+
900  // final swaps
+
901  for (int i=0; i<(numQubits/2); i++) {
+
902 
+
903  int qb1 = qubits[i];
+
904  int qb2 = qubits[numQubits-i-1];
+
905 
+
906  statevec_swapQubitAmps(qureg, qb1, qb2);
+
907  if (qureg.isDensityMatrix)
+
908  statevec_swapQubitAmps(qureg, qb1 + densShift, qb2 + densShift);
+
909  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
+
910  }
+
911 }
-

References GATE_HADAMARD, GATE_SWAP, Qureg::isDensityMatrix, M_PI, Qureg::numQubitsRepresented, qasm_recordControlledGate(), qasm_recordGate(), qasm_recordNamedPhaseFunc(), qreal, SCALED_PRODUCT, shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_hadamard(), statevec_swapQubitAmps(), and UNSIGNED.

+

References GATE_HADAMARD, GATE_SWAP, Qureg::isDensityMatrix, M_PI, Qureg::numQubitsRepresented, qasm_recordControlledGate(), qasm_recordGate(), qasm_recordNamedPhaseFunc(), qreal, SCALED_PRODUCT, shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_hadamard(), statevec_swapQubitAmps(), and UNSIGNED.

-

Referenced by applyFullQFT(), and applyQFT().

+

Referenced by applyFullQFT(), and applyQFT().

@@ -487,19 +487,19 @@

-

Definition at line 827 of file QuEST_common.c.

-
827  {
-
828 
-
829  if (time == 0)
-
830  return;
-
831 
-
832  for (int r=0; r<reps; r++)
-
833  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
-
834 }
+

Definition at line 840 of file QuEST_common.c.

+
840  {
+
841 
+
842  if (time == 0)
+
843  return;
+
844 
+
845  for (int r=0; r<reps; r++)
+
846  applySymmetrizedTrotterCircuit(qureg, hamil, time/reps, order);
+
847 }
-

References applySymmetrizedTrotterCircuit().

+

References applySymmetrizedTrotterCircuit().

-

Referenced by applyTrotterCircuit().

+

Referenced by applyTrotterCircuit().

@@ -529,32 +529,32 @@

-

Definition at line 1335 of file QuEST_cpu.c.

-
1335  {
-
1336 
-
1337  // the 2^numQubits values will be evenly split between the env.numRanks nodes
-
1338  DiagonalOp op;
-
1339  op.numQubits = numQubits;
-
1340  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
-
1341  op.chunkId = env.rank;
-
1342  op.numChunks = env.numRanks;
-
1343 
-
1344  // allocate CPU memory (initialised to zero)
-
1345  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
-
1346  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+

Definition at line 1346 of file QuEST_cpu.c.

+
1346  {
1347 
-
1348  // check cpu memory allocation was successful
-
1349  if ( !op.real || !op.imag ) {
-
1350  printf("Could not allocate memory!\n");
-
1351  exit(EXIT_FAILURE);
-
1352  }
-
1353 
-
1354  return op;
-
1355 }
+
1348  // the 2^numQubits values will be evenly split between the env.numRanks nodes
+
1349  DiagonalOp op;
+
1350  op.numQubits = numQubits;
+
1351  op.numElemsPerChunk = (1LL << numQubits) / env.numRanks;
+
1352  op.chunkId = env.rank;
+
1353  op.numChunks = env.numRanks;
+
1354 
+
1355  // allocate CPU memory (initialised to zero)
+
1356  op.real = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1357  op.imag = (qreal*) calloc(op.numElemsPerChunk, sizeof(qreal));
+
1358 
+
1359  // check cpu memory allocation was successful
+
1360  if ( !op.real || !op.imag ) {
+
1361  printf("Could not allocate memory!\n");
+
1362  exit(EXIT_FAILURE);
+
1363  }
+
1364 
+
1365  return op;
+
1366 }
-

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

+

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, qreal, QuESTEnv::rank, and DiagonalOp::real.

-

Referenced by createDiagonalOp(), and createDiagonalOpFromPauliHamilFile().

+

Referenced by createDiagonalOp(), and createDiagonalOpFromPauliHamilFile().

@@ -574,15 +574,15 @@

-

Definition at line 1357 of file QuEST_cpu.c.

-
1357  {
-
1358  free(op.real);
-
1359  free(op.imag);
-
1360 }
+

Definition at line 1368 of file QuEST_cpu.c.

+
1368  {
+
1369  free(op.real);
+
1370  free(op.imag);
+
1371 }

References DiagonalOp::deviceOperator, DiagonalOp::imag, and DiagonalOp::real.

-

Referenced by destroyDiagonalOp().

+

Referenced by destroyDiagonalOp().

@@ -612,72 +612,72 @@

-

Definition at line 1366 of file QuEST_cpu.c.

-
1366  {
-
1367 
-
1368  /* each node modifies its op sub-partition, evaluating the full hamil
-
1369  * for every element in the sub-partition
-
1370  */
-
1371 
-
1372  // unpack op
-
1373  long long int offset = op.chunkId * op.numElemsPerChunk;
-
1374  long long int numElems = op.numElemsPerChunk;
-
1375  qreal* opRe = op.real;
-
1376  qreal* opIm = op.imag;
-
1377 
-
1378  // unpack hamil
-
1379  int numTerms = hamil.numSumTerms;
-
1380  int numQubits = hamil.numQubits;
-
1381  qreal* coeffs = hamil.termCoeffs;
-
1382  enum pauliOpType* codes = hamil.pauliCodes;
-
1383 
-
1384  // private OpenMP vars
-
1385  long long int i, globalInd;
-
1386  qreal elem;
-
1387  int t, q, isOddNumOnes, sign;
+

Definition at line 1377 of file QuEST_cpu.c.

+
1377  {
+
1378 
+
1379  /* each node modifies its op sub-partition, evaluating the full hamil
+
1380  * for every element in the sub-partition
+
1381  */
+
1382 
+
1383  // unpack op
+
1384  long long int offset = op.chunkId * op.numElemsPerChunk;
+
1385  long long int numElems = op.numElemsPerChunk;
+
1386  qreal* opRe = op.real;
+
1387  qreal* opIm = op.imag;
1388 
-
1389 # ifdef _OPENMP
-
1390 # pragma omp parallel \
-
1391  default (none) \
-
1392  shared (offset,numElems, opRe,opIm, numTerms,numQubits,coeffs,codes) \
-
1393  private (i,globalInd, elem, isOddNumOnes,t,q,sign)
-
1394 # endif
-
1395  {
-
1396 # ifdef _OPENMP
-
1397 # pragma omp for schedule (static)
-
1398 # endif
-
1399  for (i=0; i<numElems; i++) {
-
1400 
-
1401  globalInd = i + offset;
-
1402  elem = 0;
-
1403 
-
1404  // add every Hamiltonian coefficient to this element, either + or -
-
1405  for (t=0; t<numTerms; t++) {
-
1406 
-
1407  // determine parity of ones (in globalInd basis state) of the current term's targets
-
1408  isOddNumOnes = 0;
-
1409  for (q=0; q<numQubits; q++)
-
1410  if (codes[q + t*numQubits] == PAULI_Z)
-
1411  if (extractBit(q, globalInd))
-
1412  isOddNumOnes = !isOddNumOnes;
-
1413 
-
1414  // add +- term coeff (avoiding thread divergence)
-
1415  sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1)
-
1416  elem += coeffs[t] * sign;
-
1417  }
-
1418 
-
1419  opRe[i] = elem;
-
1420  opIm[i] = 0;
-
1421  }
-
1422  }
-
1423 
-
1424  // we don't synch to GPU, because in GPU mode, the GPU populates and synchs to RAM
-
1425  // agnostic_syncDiagonalOp(op);
-
1426 }
+
1389  // unpack hamil
+
1390  int numTerms = hamil.numSumTerms;
+
1391  int numQubits = hamil.numQubits;
+
1392  qreal* coeffs = hamil.termCoeffs;
+
1393  enum pauliOpType* codes = hamil.pauliCodes;
+
1394 
+
1395  // private OpenMP vars
+
1396  long long int i, globalInd;
+
1397  qreal elem;
+
1398  int t, q, isOddNumOnes, sign;
+
1399 
+
1400 # ifdef _OPENMP
+
1401 # pragma omp parallel \
+
1402  default (none) \
+
1403  shared (offset,numElems, opRe,opIm, numTerms,numQubits,coeffs,codes) \
+
1404  private (i,globalInd, elem, isOddNumOnes,t,q,sign)
+
1405 # endif
+
1406  {
+
1407 # ifdef _OPENMP
+
1408 # pragma omp for schedule (static)
+
1409 # endif
+
1410  for (i=0; i<numElems; i++) {
+
1411 
+
1412  globalInd = i + offset;
+
1413  elem = 0;
+
1414 
+
1415  // add every Hamiltonian coefficient to this element, either + or -
+
1416  for (t=0; t<numTerms; t++) {
+
1417 
+
1418  // determine parity of ones (in globalInd basis state) of the current term's targets
+
1419  isOddNumOnes = 0;
+
1420  for (q=0; q<numQubits; q++)
+
1421  if (codes[q + t*numQubits] == PAULI_Z)
+
1422  if (extractBit(q, globalInd))
+
1423  isOddNumOnes = !isOddNumOnes;
+
1424 
+
1425  // add +- term coeff (avoiding thread divergence)
+
1426  sign = 1 - 2*isOddNumOnes; // (-1 if isOddNumOnes, else +1)
+
1427  elem += coeffs[t] * sign;
+
1428  }
+
1429 
+
1430  opRe[i] = elem;
+
1431  opIm[i] = 0;
+
1432  }
+
1433  }
+
1434 
+
1435  // we don't synch to GPU, because in GPU mode, the GPU populates and synchs to RAM
+
1436  // agnostic_syncDiagonalOp(op);
+
1437 }

References DiagonalOp::chunkId, extractBit(), DiagonalOp::imag, DiagonalOp::numElemsPerChunk, PauliHamil::numQubits, DiagonalOp::numQubits, PauliHamil::numSumTerms, PAULI_Z, PauliHamil::pauliCodes, qreal, DiagonalOp::real, and PauliHamil::termCoeffs.

-

Referenced by createDiagonalOpFromPauliHamilFile(), and initDiagonalOpFromPauliHamil().

+

Referenced by createDiagonalOpFromPauliHamilFile(), and initDiagonalOpFromPauliHamil().

@@ -725,50 +725,50 @@

-

Definition at line 4188 of file QuEST_cpu.c.

-
4188  {
-
4189 
-
4190  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
4191  // these may be negative or above qureg.numAmpsPerChunk
-
4192  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
-
4193  long long int localEndInd = localStartInd + numElems; // exclusive
-
4194 
-
4195  // add this to a local index to get corresponding elem in reals & imags
-
4196  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
-
4197 
-
4198  // restrict these indices to fit into this chunk
-
4199  if (localStartInd < 0)
-
4200  localStartInd = 0;
-
4201  if (localEndInd > op.numElemsPerChunk)
-
4202  localEndInd = op.numElemsPerChunk;
-
4203  // they may now be out of order = no iterations
-
4204 
-
4205  // unpacking OpenMP vars
-
4206  long long int index;
-
4207  qreal* vecRe = op.real;
-
4208  qreal* vecIm = op.imag;
-
4209 
-
4210 # ifdef _OPENMP
-
4211 # pragma omp parallel \
-
4212  default (none) \
-
4213  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
-
4214  private (index)
-
4215 # endif
-
4216  {
-
4217 # ifdef _OPENMP
-
4218 # pragma omp for schedule (static)
-
4219 # endif
-
4220  // iterate these local inds - this might involve no iterations
-
4221  for (index=localStartInd; index < localEndInd; index++) {
-
4222  vecRe[index] = real[index + offset];
-
4223  vecIm[index] = imag[index + offset];
-
4224  }
-
4225  }
-
4226 }
+

Definition at line 4228 of file QuEST_cpu.c.

+
4228  {
+
4229 
+
4230  // local start/end indices of the given amplitudes, assuming they fit in this chunk
+
4231  // these may be negative or above qureg.numAmpsPerChunk
+
4232  long long int localStartInd = startInd - op.chunkId*op.numElemsPerChunk;
+
4233  long long int localEndInd = localStartInd + numElems; // exclusive
+
4234 
+
4235  // add this to a local index to get corresponding elem in reals & imags
+
4236  long long int offset = op.chunkId*op.numElemsPerChunk - startInd;
+
4237 
+
4238  // restrict these indices to fit into this chunk
+
4239  if (localStartInd < 0)
+
4240  localStartInd = 0;
+
4241  if (localEndInd > op.numElemsPerChunk)
+
4242  localEndInd = op.numElemsPerChunk;
+
4243  // they may now be out of order = no iterations
+
4244 
+
4245  // unpacking OpenMP vars
+
4246  long long int index;
+
4247  qreal* vecRe = op.real;
+
4248  qreal* vecIm = op.imag;
+
4249 
+
4250 # ifdef _OPENMP
+
4251 # pragma omp parallel \
+
4252  default (none) \
+
4253  shared (localStartInd,localEndInd, vecRe,vecIm, real,imag, offset) \
+
4254  private (index)
+
4255 # endif
+
4256  {
+
4257 # ifdef _OPENMP
+
4258 # pragma omp for schedule (static)
+
4259 # endif
+
4260  // iterate these local inds - this might involve no iterations
+
4261  for (index=localStartInd; index < localEndInd; index++) {
+
4262  vecRe[index] = real[index + offset];
+
4263  vecIm[index] = imag[index + offset];
+
4264  }
+
4265  }
+
4266 }

References DiagonalOp::chunkId, DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, qreal, and DiagonalOp::real.

-

Referenced by initDiagonalOp(), and setDiagonalOpElems().

+

Referenced by initDiagonalOp(), and setDiagonalOpElems().

@@ -788,14 +788,14 @@

-

Definition at line 1362 of file QuEST_cpu.c.

-
1362  {
-
1363  // nothing to do on CPU
-
1364 }
+

Definition at line 1373 of file QuEST_cpu.c.

+
1373  {
+
1374  // nothing to do on CPU
+
1375 }

References DiagonalOp::deviceOperator, DiagonalOp::imag, DiagonalOp::numElemsPerChunk, and DiagonalOp::real.

-

Referenced by syncDiagonalOp().

+

Referenced by syncDiagonalOp().

@@ -843,16 +843,16 @@

-

Definition at line 1583 of file QuEST_cpu_distributed.c.

- @@ -882,29 +882,29 @@

-

Definition at line 1607 of file QuEST_cpu_distributed.c.

-
1607  {
-
1608 
-
1609  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
-
1610  if (qureg.numChunks == 1)
-
1611  return localVal;
-
1612 
-
1613  qreal localRe = localVal.real;
-
1614  qreal localIm = localVal.imag;
-
1615  qreal globalRe, globalIm;
-
1616 
-
1617  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1618  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+

Definition at line 1618 of file QuEST_cpu_distributed.c.

+
1618  {
1619 
-
1620  Complex globalVal;
-
1621  globalVal.real = globalRe;
-
1622  globalVal.imag = globalIm;
-
1623  return globalVal;
-
1624 }
+
1620  Complex localVal = densmatr_calcExpecDiagonalOpLocal(qureg, op);
+
1621  if (qureg.numChunks == 1)
+
1622  return localVal;
+
1623 
+
1624  qreal localRe = localVal.real;
+
1625  qreal localIm = localVal.imag;
+
1626  qreal globalRe, globalIm;
+
1627 
+
1628  MPI_Allreduce(&localRe, &globalRe, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1629  MPI_Allreduce(&localIm, &globalIm, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1630 
+
1631  Complex globalVal;
+
1632  globalVal.real = globalRe;
+
1633  globalVal.imag = globalIm;
+
1634  return globalVal;
+
1635 }
-

References copySharedReduceBlock(), densmatr_calcExpecDiagonalOpLocal(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, DiagonalOp::numQubits, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+

References copySharedReduceBlock(), densmatr_calcExpecDiagonalOpLocal(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, DiagonalOp::numQubits, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

-

Referenced by calcExpecDiagonalOp().

+

Referenced by calcExpecDiagonalOp().

@@ -934,25 +934,25 @@

-

Definition at line 425 of file QuEST_cpu_distributed.c.

-
425  {
-
426 
-
427  // set qureg's pairState is to be the full pureState (on every node)
-
428  copyVecIntoMatrixPairState(qureg, pureState);
-
429 
-
430  // collect calcFidelityLocal by every machine
-
431  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
-
432 
-
433  // sum each localSum
-
434  qreal globalSum;
-
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+

Definition at line 429 of file QuEST_cpu_distributed.c.

+
429  {
+
430 
+
431  // set qureg's pairState is to be the full pureState (on every node)
+
432  copyVecIntoMatrixPairState(qureg, pureState);
+
433 
+
434  // collect calcFidelityLocal by every machine
+
435  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
436 
-
437  return globalSum;
-
438 }
+
437  // sum each localSum
+
438  qreal globalSum;
+
439  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
440 
+
441  return globalSum;
+
442 }
-

References copySharedReduceBlock(), copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, Qureg::stateVec, and swapDouble().

+

References copySharedReduceBlock(), copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, Qureg::stateVec, and swapDouble().

-

Referenced by calcFidelity().

+

Referenced by calcFidelity().

@@ -982,21 +982,21 @@

-

Definition at line 440 of file QuEST_cpu_distributed.c.

-
440  {
-
441 
- -
443 
-
444  qreal globalSum;
-
445  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
446 
-
447  qreal dist = sqrt(globalSum);
-
448  return dist;
-
449 }
+

Definition at line 444 of file QuEST_cpu_distributed.c.

+
444  {
+
445 
+ +
447 
+
448  qreal globalSum;
+
449  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
450 
+
451  qreal dist = sqrt(globalSum);
+
452  return dist;
+
453 }
-

References copySharedReduceBlock(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+

References copySharedReduceBlock(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

-

Referenced by calcHilbertSchmidtDistance().

+

Referenced by calcHilbertSchmidtDistance().

@@ -1026,21 +1026,21 @@

-

Definition at line 451 of file QuEST_cpu_distributed.c.

-
451  {
-
452 
-
453  qreal localSum = densmatr_calcInnerProductLocal(a, b);
-
454 
-
455  qreal globalSum;
-
456  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
457 
-
458  qreal dist = globalSum;
-
459  return dist;
-
460 }
+

Definition at line 455 of file QuEST_cpu_distributed.c.

+
455  {
+
456 
+
457  qreal localSum = densmatr_calcInnerProductLocal(a, b);
+
458 
+
459  qreal globalSum;
+
460  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
461 
+
462  qreal dist = globalSum;
+
463  return dist;
+
464 }
-

References copySharedReduceBlock(), densmatr_calcInnerProductLocal(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+

References copySharedReduceBlock(), densmatr_calcInnerProductLocal(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

-

Referenced by calcDensityInnerProduct().

+

Referenced by calcDensityInnerProduct().

@@ -1082,19 +1082,19 @@

-

Definition at line 1345 of file QuEST_cpu_distributed.c.

-
1345  {
-
1346 
-
1347  // each node populates retProbs with contributions from the subset of amps in each
-
1348  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
1349 
-
1350  // then, retProbs are summed element-wise
-
1351  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1352 }
+

Definition at line 1349 of file QuEST_cpu_distributed.c.

+
1349  {
+
1350 
+
1351  // each node populates retProbs with contributions from the subset of amps in each
+
1352  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
1353 
+
1354  // then, retProbs are summed element-wise
+
1355  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1356 }
-

References densmatr_calcProbOfAllOutcomesLocal(), Qureg::numQubitsRepresented, and qreal.

+

References densmatr_calcProbOfAllOutcomesLocal(), Qureg::numQubitsRepresented, and qreal.

-

Referenced by calcProbOfAllOutcomes().

+

Referenced by calcProbOfAllOutcomes().

@@ -1130,22 +1130,22 @@

-

Definition at line 1324 of file QuEST_cpu_distributed.c.

-
1324  {
-
1325 
-
1326  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1327 
-
1328  qreal outcomeProb;
-
1329  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1330  if (outcome == 1)
-
1331  outcomeProb = 1.0 - outcomeProb;
-
1332 
-
1333  return outcomeProb;
-
1334 }
+

Definition at line 1328 of file QuEST_cpu_distributed.c.

+
1328  {
+
1329 
+
1330  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
+
1331 
+
1332  qreal outcomeProb;
+
1333  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1334  if (outcome == 1)
+
1335  outcomeProb = 1.0 - outcomeProb;
+
1336 
+
1337  return outcomeProb;
+
1338 }
-

References densmatr_findProbabilityOfZero(), densmatr_findProbabilityOfZeroLocal(), and qreal.

+

References densmatr_findProbabilityOfZero(), densmatr_findProbabilityOfZeroLocal(), and qreal.

-

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

+

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

@@ -1167,20 +1167,20 @@

Definition at line 1354 of file QuEST_cpu_distributed.c.

-
1354  {
-
1355 
-
1356  qreal localPurity = densmatr_calcPurityLocal(qureg);
-
1357 
-
1358  qreal globalPurity;
-
1359  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1360 
-
1361  return globalPurity;
-
1362 }
+

Definition at line 1358 of file QuEST_cpu_distributed.c.

+
1358  {
+
1359 
+
1360  qreal localPurity = densmatr_calcPurityLocal(qureg);
+
1361 
+
1362  qreal globalPurity;
+
1363  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1364 
+
1365  return globalPurity;
+
1366 }
-

References copySharedReduceBlock(), densmatr_calcPurityLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

+

References copySharedReduceBlock(), densmatr_calcPurityLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

-

Referenced by calcPurity().

+

Referenced by calcPurity().

@@ -1236,9 +1236,9 @@

85  return globalTotal;
86 }
-

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

+

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

@@ -1283,86 +1283,91 @@

Definition at line 785 of file QuEST_cpu.c.

-
785  {
-
786 
-
787  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
-
788  // where n = measureQubit, q = qureg.numQubitsRepresented.
-
789  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
-
790  // stepping in sub-blocks of 2^q, killing every second.
-
791  // When outcome=1, we offset the start of these blocks by their size.
-
792  long long int innerBlockSize = (1LL << measureQubit);
-
793  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
-
794 
-
795  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
-
796  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
-
797  long long int locNumAmps = qureg.numAmpsPerChunk;
-
798  long long int globalStartInd = qureg.chunkId * locNumAmps;
-
799  int innerBit = extractBit(measureQubit, globalStartInd);
-
800  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
-
801 
-
802  // If this chunk's amps are entirely inside an outer block
-
803  if (locNumAmps <= outerBlockSize) {
-
804 
-
805  // if this is an undesired outer block, kill all elems
-
806  if (outerBit != outcome)
-
807  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
808 
-
809  // othwerwise, if this is a desired outer block, and also entirely an inner block
-
810  if (locNumAmps <= innerBlockSize) {
-
811 
-
812  // and that inner block is undesired, kill all elems
-
813  if (innerBit != outcome)
-
814  return zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
-
815  // otherwise normalise all elems
-
816  else
-
817  return normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
-
818  }
-
819 
-
820  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
- -
822  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
-
823  }
-
824 
-
825  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
-
826  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
-
827  long long int firstBlockInd;
-
828 
-
829  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
-
830  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
-
831  // inner parallelisation
-
832  if (outerBit == outcome) {
-
833 
-
834  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
835  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
836 
-
837  // *norm only the desired inner blocks in the desired outer block
- -
839  qureg, totalStateProb, innerBit==outcome,
-
840  firstBlockInd, outerBlockSize, innerBlockSize);
-
841 
-
842  // zero the undesired outer block
-
843  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
-
844  }
-
845 
-
846  } else {
-
847 
-
848  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
-
849  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
-
850 
-
851  // same thing but undesired outer blocks come first
-
852  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
- -
854  qureg, totalStateProb, innerBit==outcome,
-
855  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
-
856  }
-
857  }
-
858 
-
859 }
+

Definition at line 791 of file QuEST_cpu.c.

+
791  {
+
792 
+
793  // only (global) indices (as bit sequence): '* outcome *(n+q) outcome *q are spared
+
794  // where n = measureQubit, q = qureg.numQubitsRepresented.
+
795  // We can thus step in blocks of 2^q+n, killing every second, and inside the others,
+
796  // stepping in sub-blocks of 2^q, killing every second.
+
797  // When outcome=1, we offset the start of these blocks by their size.
+
798  long long int innerBlockSize = (1LL << measureQubit);
+
799  long long int outerBlockSize = (1LL << (measureQubit + qureg.numQubitsRepresented));
+
800 
+
801  // Because there are 2^a number of nodes(/chunks), each node will contain 2^b number of blocks,
+
802  // or each block will span 2^c number of nodes. Similarly for the innerblocks.
+
803  long long int locNumAmps = qureg.numAmpsPerChunk;
+
804  long long int globalStartInd = qureg.chunkId * locNumAmps;
+
805  int innerBit = extractBit(measureQubit, globalStartInd);
+
806  int outerBit = extractBit(measureQubit + qureg.numQubitsRepresented, globalStartInd);
+
807 
+
808  // If this chunk's amps are entirely inside an outer block
+
809  if (locNumAmps <= outerBlockSize) {
+
810 
+
811  // if this is an undesired outer block, kill all elems
+
812  if (outerBit != outcome) {
+
813  zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
+
814  return;
+
815  }
+
816 
+
817  // othwerwise, if this is a desired outer block, and also entirely an inner block
+
818  if (locNumAmps <= innerBlockSize) {
+
819 
+
820  // and that inner block is undesired, kill all elems
+
821  if (innerBit != outcome)
+
822  zeroSomeAmps(qureg, 0, qureg.numAmpsPerChunk);
+
823  // otherwise normalise all elems
+
824  else
+
825  normaliseSomeAmps(qureg, totalStateProb, 0, qureg.numAmpsPerChunk);
+
826 
+
827  return;
+
828  }
+
829 
+
830  // otherwise this is a desired outer block which contains 2^a inner blocks; kill/renorm every second inner block
+ +
832  qureg, totalStateProb, innerBit==outcome, 0, qureg.numAmpsPerChunk, innerBlockSize);
+
833  return;
+
834  }
+
835 
+
836  // Otherwise, this chunk's amps contain multiple outer blocks (and hence multiple inner blocks)
+
837  long long int numOuterDoubleBlocks = locNumAmps / (2*outerBlockSize);
+
838  long long int firstBlockInd;
+
839 
+
840  // alternate norming* and zeroing the outer blocks (with order based on the desired outcome)
+
841  // These loops aren't parallelised, since they could have 1 or 2 iterations and will prevent
+
842  // inner parallelisation
+
843  if (outerBit == outcome) {
+
844 
+
845  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
+
846  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
+
847 
+
848  // *norm only the desired inner blocks in the desired outer block
+ +
850  qureg, totalStateProb, innerBit==outcome,
+
851  firstBlockInd, outerBlockSize, innerBlockSize);
+
852 
+
853  // zero the undesired outer block
+
854  zeroSomeAmps(qureg, firstBlockInd + outerBlockSize, outerBlockSize);
+
855  }
+
856 
+
857  } else {
+
858 
+
859  for (long long int outerDubBlockInd = 0; outerDubBlockInd < numOuterDoubleBlocks; outerDubBlockInd++) {
+
860  firstBlockInd = outerDubBlockInd*2*outerBlockSize;
+
861 
+
862  // same thing but undesired outer blocks come first
+
863  zeroSomeAmps(qureg, firstBlockInd, outerBlockSize);
+ +
865  qureg, totalStateProb, innerBit==outcome,
+
866  firstBlockInd + outerBlockSize, outerBlockSize, innerBlockSize);
+
867  }
+
868  }
+
869 
+
870 }
-

References alternateNormZeroingSomeAmpBlocks(), Qureg::chunkId, Qureg::deviceStateVec, extractBit(), normaliseSomeAmps(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and zeroSomeAmps().

+

References alternateNormZeroingSomeAmpBlocks(), Qureg::chunkId, Qureg::deviceStateVec, extractBit(), normaliseSomeAmps(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and zeroSomeAmps().

-

Referenced by collapseToOutcome(), and densmatr_measureWithStats().

+

Referenced by applyProjector(), collapseToOutcome(), and densmatr_measureWithStats().

@@ -1392,43 +1397,43 @@

-

Definition at line 1115 of file QuEST_cpu.c.

-
1116 {
-
1117  // dimension of the state vector
-
1118  long long int densityNumElems = qureg.numAmpsPerChunk;
-
1119 
-
1120  // Can't use qureg->stateVec as a private OMP var
-
1121  qreal *densityReal = qureg.stateVec.real;
-
1122  qreal *densityImag = qureg.stateVec.imag;
-
1123 
-
1124  // initialise the state to all zeros
-
1125  long long int index;
-
1126 # ifdef _OPENMP
-
1127 # pragma omp parallel \
-
1128  default (none) \
-
1129  shared (densityNumElems, densityReal, densityImag) \
-
1130  private (index)
-
1131 # endif
-
1132  {
-
1133 # ifdef _OPENMP
-
1134 # pragma omp for schedule (static)
-
1135 # endif
-
1136  for (index=0; index<densityNumElems; index++) {
-
1137  densityReal[index] = 0.0;
-
1138  densityImag[index] = 0.0;
-
1139  }
-
1140  }
-
1141 
-
1142  // index of the single density matrix elem to set non-zero
-
1143  long long int densityDim = 1LL << qureg.numQubitsRepresented;
-
1144  long long int densityInd = (densityDim + 1)*stateInd;
-
1145 
-
1146  // give the specified classical state prob 1
-
1147  if (qureg.chunkId == densityInd / densityNumElems){
-
1148  densityReal[densityInd % densityNumElems] = 1.0;
-
1149  densityImag[densityInd % densityNumElems] = 0.0;
-
1150  }
-
1151 }
+

Definition at line 1126 of file QuEST_cpu.c.

+
1127 {
+
1128  // dimension of the state vector
+
1129  long long int densityNumElems = qureg.numAmpsPerChunk;
+
1130 
+
1131  // Can't use qureg->stateVec as a private OMP var
+
1132  qreal *densityReal = qureg.stateVec.real;
+
1133  qreal *densityImag = qureg.stateVec.imag;
+
1134 
+
1135  // initialise the state to all zeros
+
1136  long long int index;
+
1137 # ifdef _OPENMP
+
1138 # pragma omp parallel \
+
1139  default (none) \
+
1140  shared (densityNumElems, densityReal, densityImag) \
+
1141  private (index)
+
1142 # endif
+
1143  {
+
1144 # ifdef _OPENMP
+
1145 # pragma omp for schedule (static)
+
1146 # endif
+
1147  for (index=0; index<densityNumElems; index++) {
+
1148  densityReal[index] = 0.0;
+
1149  densityImag[index] = 0.0;
+
1150  }
+
1151  }
+
1152 
+
1153  // index of the single density matrix elem to set non-zero
+
1154  long long int densityDim = 1LL << qureg.numQubitsRepresented;
+
1155  long long int densityInd = (densityDim + 1)*stateInd;
+
1156 
+
1157  // give the specified classical state prob 1
+
1158  if (qureg.chunkId == densityInd / densityNumElems){
+
1159  densityReal[densityInd % densityNumElems] = 1.0;
+
1160  densityImag[densityInd % densityNumElems] = 0.0;
+
1161  }
+
1162 }

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

@@ -1452,35 +1457,35 @@

-

Definition at line 1154 of file QuEST_cpu.c.

-
1155 {
-
1156  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
-
1157  long long int dim = (1LL << qureg.numQubitsRepresented);
-
1158  qreal probFactor = 1.0/((qreal) dim);
-
1159 
-
1160  // Can't use qureg->stateVec as a private OMP var
-
1161  qreal *densityReal = qureg.stateVec.real;
-
1162  qreal *densityImag = qureg.stateVec.imag;
-
1163 
-
1164  long long int index;
-
1165  long long int chunkSize = qureg.numAmpsPerChunk;
-
1166  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1167 # ifdef _OPENMP
-
1168 # pragma omp parallel \
-
1169  default (none) \
-
1170  shared (chunkSize, densityReal, densityImag, probFactor) \
-
1171  private (index)
-
1172 # endif
-
1173  {
-
1174 # ifdef _OPENMP
-
1175 # pragma omp for schedule (static)
-
1176 # endif
-
1177  for (index=0; index<chunkSize; index++) {
-
1178  densityReal[index] = probFactor;
-
1179  densityImag[index] = 0.0;
-
1180  }
-
1181  }
-
1182 }
+

Definition at line 1165 of file QuEST_cpu.c.

+
1166 {
+
1167  // |+><+| = sum_i 1/sqrt(2^N) |i> 1/sqrt(2^N) <j| = sum_ij 1/2^N |i><j|
+
1168  long long int dim = (1LL << qureg.numQubitsRepresented);
+
1169  qreal probFactor = 1.0/((qreal) dim);
+
1170 
+
1171  // Can't use qureg->stateVec as a private OMP var
+
1172  qreal *densityReal = qureg.stateVec.real;
+
1173  qreal *densityImag = qureg.stateVec.imag;
+
1174 
+
1175  long long int index;
+
1176  long long int chunkSize = qureg.numAmpsPerChunk;
+
1177  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
+
1178 # ifdef _OPENMP
+
1179 # pragma omp parallel \
+
1180  default (none) \
+
1181  shared (chunkSize, densityReal, densityImag, probFactor) \
+
1182  private (index)
+
1183 # endif
+
1184  {
+
1185 # ifdef _OPENMP
+
1186 # pragma omp for schedule (static)
+
1187 # endif
+
1188  for (index=0; index<chunkSize; index++) {
+
1189  densityReal[index] = probFactor;
+
1190  densityImag[index] = 0.0;
+
1191  }
+
1192  }
+
1193 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

@@ -1514,35 +1519,35 @@

-

Definition at line 462 of file QuEST_cpu_distributed.c.

-
462  {
-
463 
-
464  if (targetQureg.numChunks==1){
-
465  // local version
-
466  // save pointers to qureg's pair state
-
467  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
-
468  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
-
469 
-
470  // populate qureg pair state with pure state (by repointing)
-
471  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
-
472  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
+

Definition at line 466 of file QuEST_cpu_distributed.c.

+
466  {
+
467 
+
468  if (targetQureg.numChunks==1){
+
469  // local version
+
470  // save pointers to qureg's pair state
+
471  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
+
472  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
473 
-
474  // populate density matrix via it's pairState
-
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
476 
-
477  // restore pointers
-
478  targetQureg.pairStateVec.real = quregPairRePtr;
-
479  targetQureg.pairStateVec.imag = quregPairImPtr;
-
480  } else {
-
481  // set qureg's pairState is to be the full pure state (on every node)
-
482  copyVecIntoMatrixPairState(targetQureg, copyQureg);
-
483 
-
484  // update every density matrix chunk using pairState
-
485  densmatr_initPureStateLocal(targetQureg, copyQureg);
-
486  }
-
487 }
+
474  // populate qureg pair state with pure state (by repointing)
+
475  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
+
476  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
+
477 
+
478  // populate density matrix via it's pairState
+
479  densmatr_initPureStateLocal(targetQureg, copyQureg);
+
480 
+
481  // restore pointers
+
482  targetQureg.pairStateVec.real = quregPairRePtr;
+
483  targetQureg.pairStateVec.imag = quregPairImPtr;
+
484  } else {
+
485  // set qureg's pairState is to be the full pure state (on every node)
+
486  copyVecIntoMatrixPairState(targetQureg, copyQureg);
+
487 
+
488  // update every density matrix chunk using pairState
+
489  densmatr_initPureStateLocal(targetQureg, copyQureg);
+
490  }
+
491 }
-

References copyVecIntoMatrixPairState(), densmatr_initPureStateLocal(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

+

References copyVecIntoMatrixPairState(), densmatr_initPureStateLocal(), Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::pairStateVec, qreal, and Qureg::stateVec.

Referenced by initPureState().

@@ -1580,18 +1585,18 @@

-

Definition at line 382 of file QuEST_common.c.

-
382  {
-
383 
-
384  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
-
385  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
386  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
387  return outcome;
-
388 }
+

Definition at line 372 of file QuEST_common.c.

+
372  {
+
373 
+
374  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
+
375  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
+
376  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
+
377  return outcome;
+
378 }
-

References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), generateMeasurementOutcome(), and qreal.

+

References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), generateMeasurementOutcome(), and qreal.

-

Referenced by measure(), and measureWithStats().

+

Referenced by measure(), and measureWithStats().

@@ -1627,37 +1632,37 @@

-

Definition at line 735 of file QuEST_cpu_distributed.c.

-
735  {
-
736  if (damping == 0)
-
737  return;
-
738 
-
739  int rankIsUpper; // rank is in the upper half of an outer block
-
740  int pairRank; // rank of corresponding chunk
-
741 
-
742  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
743  qureg.numQubitsRepresented, targetQubit);
-
744 
-
745  if (useLocalDataOnly){
-
746  densmatr_mixDampingLocal(qureg, targetQubit, damping);
-
747  } else {
-
748  // pack data to send to my pair process into the first half of pairStateVec
-
749  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
750 
-
751  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
752  qureg.numQubitsRepresented);
-
753  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
754  targetQubit, qureg.numQubitsRepresented);
-
755 
-
756  exchangePairStateVectorHalves(qureg, pairRank);
-
757  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
-
758  }
+

Definition at line 739 of file QuEST_cpu_distributed.c.

+
739  {
+
740  if (damping == 0)
+
741  return;
+
742 
+
743  int rankIsUpper; // rank is in the upper half of an outer block
+
744  int pairRank; // rank of corresponding chunk
+
745 
+
746  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
747  qureg.numQubitsRepresented, targetQubit);
+
748 
+
749  if (useLocalDataOnly){
+
750  densmatr_mixDampingLocal(qureg, targetQubit, damping);
+
751  } else {
+
752  // pack data to send to my pair process into the first half of pairStateVec
+
753  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
+
754 
+
755  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
+
756  qureg.numQubitsRepresented);
+
757  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
+
758  targetQubit, qureg.numQubitsRepresented);
759 
-
760 }
+
760  exchangePairStateVectorHalves(qureg, pairRank);
+
761  densmatr_mixDampingDistributed(qureg, targetQubit, damping);
+
762  }
+
763 
+
764 }
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_oneQubitDegradeOffDiagonal(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_oneQubitDegradeOffDiagonal(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by mixDamping().

+

Referenced by mixDamping().

@@ -1693,42 +1698,42 @@

-

Definition at line 890 of file QuEST_cpu.c.

-
890  {
-
891 
-
892  /* corresponding amplitudes live on the same node (same dimensions) */
-
893 
-
894  // unpack vars for OpenMP
-
895  qreal* combineVecRe = combineQureg.stateVec.real;
-
896  qreal* combineVecIm = combineQureg.stateVec.imag;
-
897  qreal* otherVecRe = otherQureg.stateVec.real;
-
898  qreal* otherVecIm = otherQureg.stateVec.imag;
-
899  long long int numAmps = combineQureg.numAmpsPerChunk;
-
900  long long int index;
-
901 
-
902 # ifdef _OPENMP
-
903 # pragma omp parallel \
-
904  default (none) \
-
905  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
-
906  private (index)
-
907 # endif
-
908  {
-
909 # ifdef _OPENMP
-
910 # pragma omp for schedule (static)
-
911 # endif
-
912  for (index=0; index < numAmps; index++) {
-
913  combineVecRe[index] *= 1-otherProb;
-
914  combineVecIm[index] *= 1-otherProb;
-
915 
-
916  combineVecRe[index] += otherProb * otherVecRe[index];
-
917  combineVecIm[index] += otherProb * otherVecIm[index];
-
918  }
-
919  }
-
920 }
+

Definition at line 901 of file QuEST_cpu.c.

+
901  {
+
902 
+
903  /* corresponding amplitudes live on the same node (same dimensions) */
+
904 
+
905  // unpack vars for OpenMP
+
906  qreal* combineVecRe = combineQureg.stateVec.real;
+
907  qreal* combineVecIm = combineQureg.stateVec.imag;
+
908  qreal* otherVecRe = otherQureg.stateVec.real;
+
909  qreal* otherVecIm = otherQureg.stateVec.imag;
+
910  long long int numAmps = combineQureg.numAmpsPerChunk;
+
911  long long int index;
+
912 
+
913 # ifdef _OPENMP
+
914 # pragma omp parallel \
+
915  default (none) \
+
916  shared (combineVecRe,combineVecIm,otherVecRe,otherVecIm, otherProb, numAmps) \
+
917  private (index)
+
918 # endif
+
919  {
+
920 # ifdef _OPENMP
+
921 # pragma omp for schedule (static)
+
922 # endif
+
923  for (index=0; index < numAmps; index++) {
+
924  combineVecRe[index] *= 1-otherProb;
+
925  combineVecIm[index] *= 1-otherProb;
+
926 
+
927  combineVecRe[index] += otherProb * otherVecRe[index];
+
928  combineVecIm[index] += otherProb * otherVecIm[index];
+
929  }
+
930  }
+
931 }

References Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by mixDensityMatrix().

+

Referenced by mixDensityMatrix().

@@ -1764,15 +1769,15 @@

-

Definition at line 79 of file QuEST_cpu.c.

-
79  {
-
80  qreal retain=1-dephase;
-
81  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
-
82 }
+

Definition at line 85 of file QuEST_cpu.c.

+
85  {
+
86  qreal retain=1-dephase;
+
87  densmatr_oneQubitDegradeOffDiagonal(qureg, targetQubit, retain);
+
88 }
-

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

+

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

-

Referenced by densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), and mixDephasing().

+

Referenced by densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), and mixDephasing().

@@ -1808,37 +1813,37 @@

-

Definition at line 708 of file QuEST_cpu_distributed.c.

-
708  {
-
709  if (depolLevel == 0)
-
710  return;
-
711 
-
712  int rankIsUpper; // rank is in the upper half of an outer block
-
713  int pairRank; // rank of corresponding chunk
-
714 
-
715  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
716  qureg.numQubitsRepresented, targetQubit);
-
717 
-
718  if (useLocalDataOnly){
-
719  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
-
720  } else {
-
721  // pack data to send to my pair process into the first half of pairStateVec
-
722  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
-
723 
-
724  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
-
725  qureg.numQubitsRepresented);
-
726  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
-
727  targetQubit, qureg.numQubitsRepresented);
-
728 
-
729  exchangePairStateVectorHalves(qureg, pairRank);
-
730  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
-
731  }
+

Definition at line 712 of file QuEST_cpu_distributed.c.

+
712  {
+
713  if (depolLevel == 0)
+
714  return;
+
715 
+
716  int rankIsUpper; // rank is in the upper half of an outer block
+
717  int pairRank; // rank of corresponding chunk
+
718 
+
719  int useLocalDataOnly = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
720  qureg.numQubitsRepresented, targetQubit);
+
721 
+
722  if (useLocalDataOnly){
+
723  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
+
724  } else {
+
725  // pack data to send to my pair process into the first half of pairStateVec
+
726  compressPairVectorForSingleQubitDepolarise(qureg, targetQubit);
+
727 
+
728  rankIsUpper = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit,
+
729  qureg.numQubitsRepresented);
+
730  pairRank = getChunkOuterBlockPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk,
+
731  targetQubit, qureg.numQubitsRepresented);
732 
-
733 }
+
733  exchangePairStateVectorHalves(qureg, pairRank);
+
734  densmatr_mixDepolarisingDistributed(qureg, targetQubit, depolLevel);
+
735  }
+
736 
+
737 }
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDephasing(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForSingleQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixDephasing(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by mixDepolarising().

+

Referenced by mixDepolarising().

@@ -1880,17 +1885,17 @@

-

Definition at line 654 of file QuEST_common.c.

-
654  {
-
655 
-
656  ComplexMatrix4 superOp;
-
657  populateKrausSuperOperator2(&superOp, ops, numOps);
-
658  densmatr_applyKrausSuperoperator(qureg, target, superOp);
-
659 }
+

Definition at line 644 of file QuEST_common.c.

+
644  {
+
645 
+
646  ComplexMatrix4 superOp;
+
647  populateKrausSuperOperator2(&superOp, ops, numOps);
+
648  densmatr_applyKrausSuperoperator(qureg, target, superOp);
+
649 }
-

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

+

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

-

Referenced by densmatr_mixPauli(), and mixKrausMap().

+

Referenced by densmatr_mixPauli(), and mixKrausMap().

@@ -1938,43 +1943,52 @@

-

Definition at line 697 of file QuEST_common.c.

-
697  {
-
698 
-
699  ComplexMatrixN superOp;
-
700 
-
701  /* superOp will contain 2^(4 numTargets) complex numbers.
-
702  * At double precision, superOp will cost additional memory:
-
703  * numTargs=1 -> 0.25 KiB
-
704  * numTargs=2 -> 4 KiB
-
705  * numTargs=3 -> 64 KiB
-
706  * numTargs=4 -> 1 MiB
-
707  * numTargs=5 -> 16 MiB.
-
708  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
-
709  * this costs at most double.
-
710  *
-
711  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
-
712  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
-
713  * for numTargets < 4, superOp will be kept in the stack, else in the heap
-
714  */
-
715 
-
716  if (numTargets < 4) {
-
717  // everything must live in 'if' since this macro declares local vars
-
718  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
-
719  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
720  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
721  }
-
722  else {
-
723  superOp = createComplexMatrixN(2*numTargets);
-
724  populateKrausSuperOperatorN(&superOp, ops, numOps);
-
725  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
-
726  destroyComplexMatrixN(superOp);
-
727  }
-
728 }
+

Definition at line 701 of file QuEST_common.c.

+
701  {
+
702 
+
703  ComplexMatrixN superOp;
+
704 
+
705  /* superOp will contain 2^(4 numTargets) complex numbers.
+
706  * At double precision, superOp will cost additional memory:
+
707  * numTargs=1 -> 0.25 KiB
+
708  * numTargs=2 -> 4 KiB
+
709  * numTargs=3 -> 64 KiB
+
710  * numTargs=4 -> 1 MiB
+
711  * numTargs=5 -> 16 MiB.
+
712  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
+
713  * this costs at most double.
+
714  *
+
715  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
+
716  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
+
717  * for numTargets < 4, superOp will be kept in the stack, else in the heap
+
718  */
+
719 
+
720  // if NOT on Windows, allocate ComplexN on stack depending on size
+
721  #ifndef _WIN32
+
722  if (numTargets < 4) {
+
723  // everything must live in 'if' since this macro declares local vars
+
724  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
+
725  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
726  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
727  }
+
728  else {
+
729  superOp = createComplexMatrixN(2*numTargets);
+
730  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
731  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
732  destroyComplexMatrixN(superOp);
+
733  }
+
734  // on Windows, we must always create in heap
+
735  #else
+
736  superOp = createComplexMatrixN(2*numTargets);
+
737  populateKrausSuperOperatorN(&superOp, ops, numOps);
+
738  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
+
739  destroyComplexMatrixN(superOp);
+
740  #endif
+
741 }
-

References createComplexMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperatorN().

+

References createComplexMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperatorN().

-

Referenced by mixMultiQubitKrausMap().

+

Referenced by mixMultiQubitKrausMap().

@@ -2022,32 +2036,32 @@

-

Definition at line 730 of file QuEST_common.c.

-
730  {
-
731 
-
732  // convert pauli probabilities into Kraus map
-
733  const int numOps = 4;
-
734  ComplexMatrix2 ops[numOps];
-
735  for (int n=0; n < numOps; n++)
-
736  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
-
737 
-
738  qreal facs[4] = { // literal numOps=4 for valid initialisation
-
739  sqrt(1-(probX + probY + probZ)),
-
740  sqrt(probX),
-
741  sqrt(probY),
-
742  sqrt(probZ)
-
743  };
-
744  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
-
745  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
-
746  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
-
747  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
-
748 
-
749  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
-
750 }
+

Definition at line 743 of file QuEST_common.c.

+
743  {
+
744 
+
745  // convert pauli probabilities into Kraus map
+
746  const int numOps = 4;
+
747  ComplexMatrix2 ops[4]; // [numOps];
+
748  for (int n=0; n < numOps; n++)
+
749  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
+
750 
+
751  qreal facs[4] = { // literal numOps=4 for valid initialisation
+
752  sqrt(1-(probX + probY + probZ)),
+
753  sqrt(probX),
+
754  sqrt(probY),
+
755  sqrt(probZ)
+
756  };
+
757  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
+
758  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
+
759  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
+
760  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
+
761 
+
762  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
+
763 }
-

References densmatr_mixKrausMap(), ComplexMatrix2::imag, qreal, and ComplexMatrix2::real.

+

References densmatr_mixKrausMap(), ComplexMatrix2::imag, qreal, and ComplexMatrix2::real.

-

Referenced by mixPauli().

+

Referenced by mixPauli().

@@ -2089,51 +2103,51 @@

-

Definition at line 84 of file QuEST_cpu.c.

-
84  {
-
85  qreal retain=1-dephase;
-
86 
-
87  long long int numTasks = qureg.numAmpsPerChunk;
-
88  long long int innerMaskQubit1 = 1LL << qubit1;
-
89  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
-
90  long long int innerMaskQubit2 = 1LL << qubit2;
-
91  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
-
92  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
-
93  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
-
94 
-
95  long long int thisTask;
-
96  long long int thisPatternQubit1, thisPatternQubit2;
-
97 
-
98 # ifdef _OPENMP
-
99 # pragma omp parallel \
-
100  default (none) \
-
101  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
-
102  totMaskQubit2,qureg,retain,numTasks) \
-
103  private (thisTask,thisPatternQubit1,thisPatternQubit2)
-
104 # endif
-
105  {
-
106 # ifdef _OPENMP
-
107 # pragma omp for schedule (static)
-
108 # endif
-
109  for (thisTask=0; thisTask<numTasks; thisTask++){
-
110  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
-
111  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
-
112 
-
113  // any mismatch |...0...><...1...| etc
-
114  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
-
115  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
-
116  // do dephase
-
117  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
-
118  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
-
119  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
-
120  }
-
121  }
-
122  }
-
123 }
+

Definition at line 90 of file QuEST_cpu.c.

+
90  {
+
91  qreal retain=1-dephase;
+
92 
+
93  long long int numTasks = qureg.numAmpsPerChunk;
+
94  long long int innerMaskQubit1 = 1LL << qubit1;
+
95  long long int outerMaskQubit1 = 1LL << (qubit1 + (qureg.numQubitsRepresented));
+
96  long long int innerMaskQubit2 = 1LL << qubit2;
+
97  long long int outerMaskQubit2 = 1LL << (qubit2 + (qureg.numQubitsRepresented));
+
98  long long int totMaskQubit1 = innerMaskQubit1|outerMaskQubit1;
+
99  long long int totMaskQubit2 = innerMaskQubit2|outerMaskQubit2;
+
100 
+
101  long long int thisTask;
+
102  long long int thisPatternQubit1, thisPatternQubit2;
+
103 
+
104 # ifdef _OPENMP
+
105 # pragma omp parallel \
+
106  default (none) \
+
107  shared (innerMaskQubit1,outerMaskQubit1,totMaskQubit1,innerMaskQubit2,outerMaskQubit2, \
+
108  totMaskQubit2,qureg,retain,numTasks) \
+
109  private (thisTask,thisPatternQubit1,thisPatternQubit2)
+
110 # endif
+
111  {
+
112 # ifdef _OPENMP
+
113 # pragma omp for schedule (static)
+
114 # endif
+
115  for (thisTask=0; thisTask<numTasks; thisTask++){
+
116  thisPatternQubit1 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit1;
+
117  thisPatternQubit2 = (thisTask+qureg.numAmpsPerChunk*qureg.chunkId)&totMaskQubit2;
+
118 
+
119  // any mismatch |...0...><...1...| etc
+
120  if ( (thisPatternQubit1==innerMaskQubit1) || (thisPatternQubit1==outerMaskQubit1) ||
+
121  (thisPatternQubit2==innerMaskQubit2) || (thisPatternQubit2==outerMaskQubit2) ){
+
122  // do dephase
+
123  // the lines below will degrade the off-diagonal terms |..0..><..1..| and |..1..><..0..|
+
124  qureg.stateVec.real[thisTask] = retain*qureg.stateVec.real[thisTask];
+
125  qureg.stateVec.imag[thisTask] = retain*qureg.stateVec.imag[thisTask];
+
126  }
+
127  }
+
128  }
+
129 }

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, qreal, and Qureg::stateVec.

-

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

+

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

@@ -2175,102 +2189,102 @@

-

Definition at line 762 of file QuEST_cpu_distributed.c.

-
762  {
-
763  if (depolLevel == 0)
-
764  return;
-
765  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
-
766  int pairRank; // rank of corresponding chunk
-
767  int biggerQubit, smallerQubit;
-
768 
-
769  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
-
770 
-
771  qreal eta = 2/depolLevel;
-
772  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
-
773  qreal gamma = 1+delta;
-
774  gamma = 1/(gamma*gamma*gamma);
-
775  qreal GAMMA_PARTS_1_OR_2 = 1.0;
-
776  // TODO -- test delta too small
-
777  /*
-
778  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
-
779  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
-
780  exit(1);
-
781  }
-
782  */
-
783 
-
784  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
-
785  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
-
786  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
-
787 
-
788  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
789  qureg.numQubitsRepresented, biggerQubit);
-
790  if (useLocalDataOnlyBigQubit){
-
791  // does parts 1, 2 and 3 locally in one go
-
792  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
-
793  } else {
-
794  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
-
795  qureg.numQubitsRepresented, smallerQubit);
-
796  if (useLocalDataOnlySmallQubit){
-
797  // do part 1 locally
-
798  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
-
799 
-
800  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
-
801  // part 2 will be distributed and the value of the small qubit won't matter
-
802  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
803  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
804  qureg.numQubitsRepresented);
-
805  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
806  biggerQubit, qureg.numQubitsRepresented);
-
807 
-
808  exchangePairStateVectorHalves(qureg, pairRank);
-
809  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
810 
-
811  // part 3 will be distributed but involve rearranging for the smaller qubit
-
812  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
813  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
814  qureg.numQubitsRepresented);
-
815  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
816  biggerQubit, qureg.numQubitsRepresented);
-
817 
-
818  exchangePairStateVectorHalves(qureg, pairRank);
-
819  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
-
820  } else {
-
821  // do part 1, 2 and 3 distributed
-
822  // part 1
-
823  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
824  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
-
825  qureg.numQubitsRepresented);
-
826  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
827  smallerQubit, qureg.numQubitsRepresented);
-
828 
-
829  exchangePairStateVectorHalves(qureg, pairRank);
-
830  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
831 
-
832  // part 2
-
833  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
834  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
-
835  qureg.numQubitsRepresented);
-
836  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
-
837  biggerQubit, qureg.numQubitsRepresented);
-
838 
-
839  exchangePairStateVectorHalves(qureg, pairRank);
-
840  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
-
841 
-
842  // part 3
-
843  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
-
844  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
-
845  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
-
846  exchangePairStateVectorHalves(qureg, pairRank);
-
847  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
-
848 
-
849  }
-
850  }
-
851 
-
852 }
+

Definition at line 766 of file QuEST_cpu_distributed.c.

+
766  {
+
767  if (depolLevel == 0)
+
768  return;
+
769  int rankIsUpperBiggerQubit, rankIsUpperSmallerQubit;
+
770  int pairRank; // rank of corresponding chunk
+
771  int biggerQubit, smallerQubit;
+
772 
+
773  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
+
774 
+
775  qreal eta = 2/depolLevel;
+
776  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
+
777  qreal gamma = 1+delta;
+
778  gamma = 1/(gamma*gamma*gamma);
+
779  qreal GAMMA_PARTS_1_OR_2 = 1.0;
+
780  // TODO -- test delta too small
+
781  /*
+
782  if (fabs(4*delta*(1+delta)*gamma-depolLevel)>1e-5){
+
783  printf("Numerical error in delta; for small error rates try Taylor expansion.\n");
+
784  exit(1);
+
785  }
+
786  */
+
787 
+
788  biggerQubit = qubit1 > qubit2 ? qubit1 : qubit2;
+
789  smallerQubit = qubit1 < qubit2 ? qubit1 : qubit2;
+
790  int useLocalDataOnlyBigQubit, useLocalDataOnlySmallQubit;
+
791 
+
792  useLocalDataOnlyBigQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
793  qureg.numQubitsRepresented, biggerQubit);
+
794  if (useLocalDataOnlyBigQubit){
+
795  // does parts 1, 2 and 3 locally in one go
+
796  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
+
797  } else {
+
798  useLocalDataOnlySmallQubit = densityMatrixBlockFitsInChunk(qureg.numAmpsPerChunk,
+
799  qureg.numQubitsRepresented, smallerQubit);
+
800  if (useLocalDataOnlySmallQubit){
+
801  // do part 1 locally
+
802  densmatr_mixTwoQubitDepolarisingLocalPart1(qureg, smallerQubit, biggerQubit, delta);
+
803 
+
804  // do parts 2 and 3 distributed (if part 2 is distributed part 3 is also distributed)
+
805  // part 2 will be distributed and the value of the small qubit won't matter
+
806  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
807  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
808  qureg.numQubitsRepresented);
+
809  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
810  biggerQubit, qureg.numQubitsRepresented);
+
811 
+
812  exchangePairStateVectorHalves(qureg, pairRank);
+
813  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
814 
+
815  // part 3 will be distributed but involve rearranging for the smaller qubit
+
816  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
817  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
818  qureg.numQubitsRepresented);
+
819  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
820  biggerQubit, qureg.numQubitsRepresented);
+
821 
+
822  exchangePairStateVectorHalves(qureg, pairRank);
+
823  densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(qureg, smallerQubit, biggerQubit, delta, gamma);
+
824  } else {
+
825  // do part 1, 2 and 3 distributed
+
826  // part 1
+
827  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
828  rankIsUpperSmallerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit,
+
829  qureg.numQubitsRepresented);
+
830  pairRank = getChunkOuterBlockPairId(rankIsUpperSmallerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
831  smallerQubit, qureg.numQubitsRepresented);
+
832 
+
833  exchangePairStateVectorHalves(qureg, pairRank);
+
834  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
835 
+
836  // part 2
+
837  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
838  rankIsUpperBiggerQubit = chunkIsUpperInOuterBlock(qureg.chunkId, qureg.numAmpsPerChunk, biggerQubit,
+
839  qureg.numQubitsRepresented);
+
840  pairRank = getChunkOuterBlockPairId(rankIsUpperBiggerQubit, qureg.chunkId, qureg.numAmpsPerChunk,
+
841  biggerQubit, qureg.numQubitsRepresented);
+
842 
+
843  exchangePairStateVectorHalves(qureg, pairRank);
+
844  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, GAMMA_PARTS_1_OR_2);
+
845 
+
846  // part 3
+
847  compressPairVectorForTwoQubitDepolarise(qureg, smallerQubit, biggerQubit);
+
848  pairRank = getChunkOuterBlockPairIdForPart3(rankIsUpperSmallerQubit, rankIsUpperBiggerQubit,
+
849  qureg.chunkId, qureg.numAmpsPerChunk, smallerQubit, biggerQubit, qureg.numQubitsRepresented);
+
850  exchangePairStateVectorHalves(qureg, pairRank);
+
851  densmatr_mixTwoQubitDepolarisingDistributed(qureg, smallerQubit, biggerQubit, delta, gamma);
+
852 
+
853  }
+
854  }
+
855 
+
856 }
-

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForTwoQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), getChunkOuterBlockPairIdForPart3(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

+

References Qureg::chunkId, chunkIsUpperInOuterBlock(), compressPairVectorForTwoQubitDepolarise(), densityMatrixBlockFitsInChunk(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), Qureg::deviceStateVec, exchangePairStateVectorHalves(), getChunkOuterBlockPairId(), getChunkOuterBlockPairIdForPart3(), Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, and qreal.

-

Referenced by mixTwoQubitDepolarising().

+

Referenced by mixTwoQubitDepolarising().

@@ -2318,18 +2332,29 @@

-

Definition at line 689 of file QuEST_common.c.

-
689  {
-
690 
-
691  ComplexMatrixN superOp;
-
692  macro_allocStackComplexMatrixN(superOp, 4);
-
693  populateKrausSuperOperator4(&superOp, ops, numOps);
-
694  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
-
695 }
+

Definition at line 682 of file QuEST_common.c.

+
682  {
+
683 
+
684  // if NOT on Windows, allocate ComplexN on stack
+
685  #ifndef _WIN32
+
686  ComplexMatrixN superOp;
+
687  macro_allocStackComplexMatrixN(superOp, 4);
+
688  populateKrausSuperOperator4(&superOp, ops, numOps);
+
689  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
+
690 
+
691  // but on Windows, we MUST allocated dynamically
+
692  #else
+ +
694  populateKrausSuperOperator4(&superOp, ops, numOps);
+
695  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
+
696  destroyComplexMatrixN(superOp);
+
697 
+
698  #endif
+
699 }
-

References densmatr_applyTwoQubitKrausSuperoperator(), macro_allocStackComplexMatrixN, and populateKrausSuperOperator4().

+

References createComplexMatrixN(), densmatr_applyTwoQubitKrausSuperoperator(), destroyComplexMatrixN(), macro_allocStackComplexMatrixN, and populateKrausSuperOperator4().

-

Referenced by mixTwoQubitKrausMap().

+

Referenced by mixTwoQubitKrausMap().

@@ -2369,7 +2394,7 @@

76  }
77 }
-

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

+

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

@@ -2484,7 +2509,7 @@

References getUnitVector(), Complex::imag, Complex::real, Vector::x, Vector::y, and Vector::z.

-

Referenced by qasm_recordAxisRotation(), qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

+

Referenced by qasm_recordAxisRotation(), qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

@@ -2513,7 +2538,7 @@

References macro_setConjugateMatrix.

-

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

+

Referenced by controlledUnitary(), multiControlledUnitary(), multiStateControlledUnitary(), and unitary().

@@ -2542,7 +2567,7 @@

References macro_setConjugateMatrix.

-

Referenced by controlledTwoQubitUnitary(), multiControlledTwoQubitUnitary(), and twoQubitUnitary().

+

Referenced by controlledTwoQubitUnitary(), multiControlledTwoQubitUnitary(), and twoQubitUnitary().

@@ -2573,7 +2598,7 @@

References Complex::imag, and Complex::real.

-

Referenced by compactUnitary(), and controlledCompactUnitary().

+

Referenced by compactUnitary(), and controlledCompactUnitary().

@@ -2620,7 +2645,7 @@

67  return mask;
68 }
-

Referenced by multiStateControlledUnitary().

+

Referenced by multiStateControlledUnitary().

@@ -2660,7 +2685,7 @@

56  return mask;
57 }
-

Referenced by applyMultiControlledMatrixN(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiRotateZ(), multiStateControlledUnitary(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiRotatePauli(), and validateMultiControlsMultiTargets().

+

Referenced by applyMultiControlledMatrixN(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiRotateZ(), multiStateControlledUnitary(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiRotatePauli(), and validateMultiControlsMultiTargets().

@@ -2705,7 +2730,7 @@

216 #endif
217 }
-

Referenced by seedQuESTDefault().

+

Referenced by seedQuESTDefault().

@@ -2733,7 +2758,7 @@

References Vector::x, Vector::y, and Vector::z.

-

Referenced by getUnitVector(), and validateVector().

+

Referenced by getUnitVector(), and validateVector().

@@ -2854,7 +2879,7 @@

References macro_setConjugateMatrix, and ComplexMatrixN::numQubits.

-

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

+

Referenced by controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), and multiQubitUnitary().

@@ -2896,7 +2921,7 @@

158  indices[j] += shift;
159 }
-

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiQubitUnitary(), and multiRotatePauli().

+

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), controlledMultiQubitUnitary(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiQubitUnitary(), and multiRotatePauli().

@@ -2946,7 +2971,7 @@

165  allInds[i++] += shift;
166 }
-

Referenced by agnostic_applyQFT(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by agnostic_applyQFT(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -2976,45 +3001,45 @@

-

Definition at line 4007 of file QuEST_cpu.c.

-
4007  {
-
4008 
-
4009  // each node/chunk modifies only its values in an embarrassingly parallelisable way
-
4010  long long int numAmps = qureg.numAmpsPerChunk;
-
4011 
-
4012  qreal* stateRe = qureg.stateVec.real;
-
4013  qreal* stateIm = qureg.stateVec.imag;
-
4014  qreal* opRe = op.real;
-
4015  qreal* opIm = op.imag;
-
4016 
-
4017  qreal a,b,c,d;
-
4018  long long int index;
-
4019 
-
4020 # ifdef _OPENMP
-
4021 # pragma omp parallel \
-
4022  shared (stateRe,stateIm, opRe,opIm, numAmps) \
-
4023  private (index, a,b,c,d)
-
4024 # endif
-
4025  {
-
4026 # ifdef _OPENMP
-
4027 # pragma omp for schedule (static)
-
4028 # endif
-
4029  for (index=0LL; index<numAmps; index++) {
-
4030  a = stateRe[index];
-
4031  b = stateIm[index];
-
4032  c = opRe[index];
-
4033  d = opIm[index];
-
4034 
-
4035  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
-
4036  stateRe[index] = a*c - b*d;
-
4037  stateIm[index] = a*d + b*c;
-
4038  }
-
4039  }
-
4040 }
+

Definition at line 4047 of file QuEST_cpu.c.

+
4047  {
+
4048 
+
4049  // each node/chunk modifies only its values in an embarrassingly parallelisable way
+
4050  long long int numAmps = qureg.numAmpsPerChunk;
+
4051 
+
4052  qreal* stateRe = qureg.stateVec.real;
+
4053  qreal* stateIm = qureg.stateVec.imag;
+
4054  qreal* opRe = op.real;
+
4055  qreal* opIm = op.imag;
+
4056 
+
4057  qreal a,b,c,d;
+
4058  long long int index;
+
4059 
+
4060 # ifdef _OPENMP
+
4061 # pragma omp parallel \
+
4062  shared (stateRe,stateIm, opRe,opIm, numAmps) \
+
4063  private (index, a,b,c,d)
+
4064 # endif
+
4065  {
+
4066 # ifdef _OPENMP
+
4067 # pragma omp for schedule (static)
+
4068 # endif
+
4069  for (index=0LL; index<numAmps; index++) {
+
4070  a = stateRe[index];
+
4071  b = stateIm[index];
+
4072  c = opRe[index];
+
4073  d = opIm[index];
+
4074 
+
4075  // (a + b i)(c + d i) = (a c - b d) + i (a d + b c)
+
4076  stateRe[index] = a*c - b*d;
+
4077  stateIm[index] = a*d + b*c;
+
4078  }
+
4079  }
+
4080 }

References DiagonalOp::imag, Qureg::numAmpsPerChunk, qreal, DiagonalOp::real, and Qureg::stateVec.

-

Referenced by applyDiagonalOp().

+

Referenced by applyDiagonalOp().

@@ -3104,106 +3129,106 @@

-

Definition at line 4305 of file QuEST_cpu.c.

-
4310 {
-
4311  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4312 
-
4313  // note partitions of qubits, coeffs, exponents and overrideInds are stored flat
-
4314 
-
4315  // thread-shared vaes
-
4316  int chunkId = qureg.chunkId;
-
4317  long long int numAmps = qureg.numAmpsPerChunk;
-
4318  qreal* stateRe = qureg.stateVec.real;
-
4319  qreal* stateIm = qureg.stateVec.imag;
-
4320 
-
4321  // thread-private vars
-
4322  long long int index, globalAmpInd;
-
4323  int r, q, i, t, found, flatInd;
-
4324  qreal phase, c, s, re, im;
-
4325 
-
4326  // each thread has a private static array of length >= numRegs (private var-length is illegal)
-
4327  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
-
4328 
-
4329 # ifdef _OPENMP
-
4330 # pragma omp parallel \
-
4331  default (none) \
-
4332  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, coeffs,exponents,numTermsPerReg, overrideInds,overridePhases,numOverrides, conj) \
-
4333  private (index,globalAmpInd, r,q,i,t,flatInd, found, phaseInds,phase, c,s,re,im)
-
4334 # endif
-
4335  {
-
4336 # ifdef _OPENMP
-
4337 # pragma omp for schedule (static)
-
4338 # endif
-
4339  for (index=0LL; index<numAmps; index++) {
-
4340 
-
4341  // determine global amplitude index
-
4342  globalAmpInd = chunkId * numAmps + index;
-
4343 
-
4344  // determine phase indices
-
4345  flatInd = 0;
-
4346  for (r=0; r<numRegs; r++) {
-
4347  phaseInds[r] = 0LL;
-
4348 
-
4349  if (encoding == UNSIGNED) {
-
4350  for (q=0; q<numQubitsPerReg[r]; q++)
-
4351  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
-
4352  }
-
4353  else if (encoding == TWOS_COMPLEMENT) {
-
4354  for (q=0; q<numQubitsPerReg[r]-1; q++)
-
4355  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
4356  // use final qubit to indicate sign
-
4357  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
4358  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
-
4359  }
-
4360  }
-
4361 
-
4362  // determine if this phase index has an overriden value (i < numOverrides)
-
4363  for (i=0; i<numOverrides; i++) {
-
4364  found = 1;
-
4365  for (r=0; r<numRegs; r++) {
-
4366  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
-
4367  found = 0;
-
4368  break;
-
4369  }
-
4370  }
-
4371  if (found)
-
4372  break;
-
4373  }
-
4374 
-
4375  // compute the phase (unless overriden)
-
4376  phase = 0;
-
4377  if (i < numOverrides)
-
4378  phase = overridePhases[i];
-
4379  else {
-
4380  flatInd = 0;
-
4381  for (r=0; r<numRegs; r++) {
-
4382  for (t=0; t<numTermsPerReg[r]; t++) {
-
4383  phase += coeffs[flatInd] * pow(phaseInds[r], exponents[flatInd]);
-
4384  flatInd++;
-
4385  }
-
4386  }
-
4387  }
-
4388 
-
4389  // negate phase to conjugate operator
-
4390  if (conj)
-
4391  phase *= -1;
-
4392 
-
4393  // modify amp to amp * exp(i phase)
-
4394  c = cos(phase);
-
4395  s = sin(phase);
-
4396  re = stateRe[index];
-
4397  im = stateIm[index];
-
4398 
-
4399  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4400  stateRe[index] = re*c - im*s;
-
4401  stateIm[index] = re*s + im*c;
-
4402  }
-
4403  }
-
4404 }
+

Definition at line 4345 of file QuEST_cpu.c.

+
4350 {
+
4351  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4352 
+
4353  // note partitions of qubits, coeffs, exponents and overrideInds are stored flat
+
4354 
+
4355  // thread-shared vaes
+
4356  int chunkId = qureg.chunkId;
+
4357  long long int numAmps = qureg.numAmpsPerChunk;
+
4358  qreal* stateRe = qureg.stateVec.real;
+
4359  qreal* stateIm = qureg.stateVec.imag;
+
4360 
+
4361  // thread-private vars
+
4362  long long int index, globalAmpInd;
+
4363  int r, q, i, t, found, flatInd;
+
4364  qreal phase, c, s, re, im;
+
4365 
+
4366  // each thread has a private static array of length >= numRegs (private var-length is illegal)
+
4367  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
+
4368 
+
4369 # ifdef _OPENMP
+
4370 # pragma omp parallel \
+
4371  default (none) \
+
4372  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, coeffs,exponents,numTermsPerReg, overrideInds,overridePhases,numOverrides, conj) \
+
4373  private (index,globalAmpInd, r,q,i,t,flatInd, found, phaseInds,phase, c,s,re,im)
+
4374 # endif
+
4375  {
+
4376 # ifdef _OPENMP
+
4377 # pragma omp for schedule (static)
+
4378 # endif
+
4379  for (index=0LL; index<numAmps; index++) {
+
4380 
+
4381  // determine global amplitude index
+
4382  globalAmpInd = chunkId * numAmps + index;
+
4383 
+
4384  // determine phase indices
+
4385  flatInd = 0;
+
4386  for (r=0; r<numRegs; r++) {
+
4387  phaseInds[r] = 0LL;
+
4388 
+
4389  if (encoding == UNSIGNED) {
+
4390  for (q=0; q<numQubitsPerReg[r]; q++)
+
4391  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
+
4392  }
+
4393  else if (encoding == TWOS_COMPLEMENT) {
+
4394  for (q=0; q<numQubitsPerReg[r]-1; q++)
+
4395  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
4396  // use final qubit to indicate sign
+
4397  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
4398  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
+
4399  }
+
4400  }
+
4401 
+
4402  // determine if this phase index has an overriden value (i < numOverrides)
+
4403  for (i=0; i<numOverrides; i++) {
+
4404  found = 1;
+
4405  for (r=0; r<numRegs; r++) {
+
4406  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
+
4407  found = 0;
+
4408  break;
+
4409  }
+
4410  }
+
4411  if (found)
+
4412  break;
+
4413  }
+
4414 
+
4415  // compute the phase (unless overriden)
+
4416  phase = 0;
+
4417  if (i < numOverrides)
+
4418  phase = overridePhases[i];
+
4419  else {
+
4420  flatInd = 0;
+
4421  for (r=0; r<numRegs; r++) {
+
4422  for (t=0; t<numTermsPerReg[r]; t++) {
+
4423  phase += coeffs[flatInd] * pow(phaseInds[r], exponents[flatInd]);
+
4424  flatInd++;
+
4425  }
+
4426  }
+
4427  }
+
4428 
+
4429  // negate phase to conjugate operator
+
4430  if (conj)
+
4431  phase *= -1;
+
4432 
+
4433  // modify amp to amp * exp(i phase)
+
4434  c = cos(phase);
+
4435  s = sin(phase);
+
4436  re = stateRe[index];
+
4437  im = stateIm[index];
+
4438 
+
4439  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4440  stateRe[index] = re*c - im*s;
+
4441  stateIm[index] = re*s + im*c;
+
4442  }
+
4443  }
+
4444 }

References Qureg::chunkId, extractBit(), MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

@@ -3293,164 +3318,164 @@

-

Definition at line 4406 of file QuEST_cpu.c.

-
4412  {
-
4413  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4414 
-
4415  // note partitions of qubits, overrideInds are stored flat
-
4416 
-
4417  // thread-shared vaes
-
4418  int chunkId = qureg.chunkId;
-
4419  long long int numAmps = qureg.numAmpsPerChunk;
-
4420  qreal* stateRe = qureg.stateVec.real;
-
4421  qreal* stateIm = qureg.stateVec.imag;
-
4422 
-
4423  // thread-private vars
-
4424  long long int index, globalAmpInd;
-
4425  int r, q, i, found, flatInd;
-
4426  qreal phase, norm, prod, dist, c, s, re, im;
-
4427 
-
4428  // each thread has a private static array of length >= numRegs (private var-length is illegal)
-
4429  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
-
4430 
-
4431 # ifdef _OPENMP
-
4432 # pragma omp parallel \
-
4433  default (none) \
-
4434  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, phaseFuncName,params,numParams, overrideInds,overridePhases,numOverrides, conj) \
-
4435  private (index,globalAmpInd, r,q,i,flatInd, found, phaseInds,phase,norm,prod,dist, c,s,re,im)
-
4436 # endif
-
4437  {
-
4438 # ifdef _OPENMP
-
4439 # pragma omp for schedule (static)
-
4440 # endif
-
4441  for (index=0LL; index<numAmps; index++) {
-
4442 
-
4443  // determine global amplitude index
-
4444  globalAmpInd = chunkId * numAmps + index;
-
4445 
-
4446  // determine phase indices
-
4447  flatInd = 0;
-
4448  for (r=0; r<numRegs; r++) {
-
4449  phaseInds[r] = 0LL;
-
4450 
-
4451  if (encoding == UNSIGNED) {
-
4452  for (q=0; q<numQubitsPerReg[r]; q++)
-
4453  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
-
4454  }
-
4455  else if (encoding == TWOS_COMPLEMENT) {
-
4456  for (q=0; q<numQubitsPerReg[r]-1; q++)
-
4457  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
-
4458  // use final qubit to indicate sign
-
4459  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
-
4460  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
-
4461  }
-
4462  }
-
4463 
-
4464  // determine if this phase index has an overriden value (i < numOverrides)
-
4465  for (i=0; i<numOverrides; i++) {
-
4466  found = 1;
-
4467  for (r=0; r<numRegs; r++) {
-
4468  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
-
4469  found = 0;
-
4470  break;
-
4471  }
-
4472  }
-
4473  if (found)
-
4474  break;
-
4475  }
-
4476 
-
4477  // compute the phase (unless overriden)
-
4478  phase = 0;
-
4479  if (i < numOverrides)
-
4480  phase = overridePhases[i];
-
4481  else {
-
4482  // compute norm related phases
-
4483  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
-
4484  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
-
4485  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
4486 
-
4487  norm = 0;
-
4488  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
-
4489  for (r=0; r<numRegs; r++)
-
4490  norm += (phaseInds[r] - params[2+r])*(phaseInds[r] - params[2+r]);
-
4491  }
-
4492  else
-
4493  for (r=0; r<numRegs; r++)
-
4494  norm += phaseInds[r]*phaseInds[r];
-
4495  norm = sqrt(norm);
-
4496 
-
4497  if (phaseFuncName == NORM)
-
4498  phase = norm;
-
4499  else if (phaseFuncName == INVERSE_NORM)
-
4500  phase = (norm == 0.)? params[0] : 1/norm;
-
4501  else if (phaseFuncName == SCALED_NORM)
-
4502  phase = params[0] * norm;
-
4503  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
-
4504  phase = (norm == 0.)? params[1] : params[0] / norm;
-
4505  }
-
4506  // compute product related phases
-
4507  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
-
4508  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
-
4509 
-
4510  prod = 1;
-
4511  for (r=0; r<numRegs; r++)
-
4512  prod *= phaseInds[r];
-
4513 
-
4514  if (phaseFuncName == PRODUCT)
-
4515  phase = prod;
-
4516  else if (phaseFuncName == INVERSE_PRODUCT)
-
4517  phase = (prod == 0.)? params[0] : 1/prod;
-
4518  else if (phaseFuncName == SCALED_PRODUCT)
-
4519  phase = params[0] * prod;
-
4520  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
-
4521  phase = (prod == 0.)? params[1] : params[0] / prod;
-
4522  }
-
4523  // compute Euclidean distance related phases
-
4524  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
-
4525  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
-
4526  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
4527 
-
4528  dist = 0;
-
4529  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
-
4530  for (r=0; r<numRegs; r+=2)
-
4531  dist += (phaseInds[r+1] - phaseInds[r] - params[2+r/2])*(phaseInds[r+1] - phaseInds[r] - params[2+r/2]);
-
4532  }
-
4533  else
-
4534  for (r=0; r<numRegs; r+=2)
-
4535  dist += (phaseInds[r+1] - phaseInds[r])*(phaseInds[r+1] - phaseInds[r]);
-
4536  dist = sqrt(dist);
-
4537 
-
4538  if (phaseFuncName == DISTANCE)
-
4539  phase = dist;
-
4540  else if (phaseFuncName == INVERSE_DISTANCE)
-
4541  phase = (dist == 0.)? params[0] : 1/dist;
-
4542  else if (phaseFuncName == SCALED_DISTANCE)
-
4543  phase = params[0] * dist;
-
4544  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
-
4545  phase = (dist == 0.)? params[1] : params[0] / dist;
-
4546  }
-
4547  }
-
4548 
-
4549  // negate phase to conjugate operator
-
4550  if (conj)
-
4551  phase *= -1;
-
4552 
-
4553  // modify amp to amp * exp(i phase)
-
4554  c = cos(phase);
-
4555  s = sin(phase);
-
4556  re = stateRe[index];
-
4557  im = stateIm[index];
-
4558 
-
4559  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4560  stateRe[index] = re*c - im*s;
-
4561  stateIm[index] = re*s + im*c;
-
4562  }
-
4563  }
-
4564 }
+

Definition at line 4446 of file QuEST_cpu.c.

+
4452  {
+
4453  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4454 
+
4455  // note partitions of qubits, overrideInds are stored flat
+
4456 
+
4457  // thread-shared vaes
+
4458  int chunkId = qureg.chunkId;
+
4459  long long int numAmps = qureg.numAmpsPerChunk;
+
4460  qreal* stateRe = qureg.stateVec.real;
+
4461  qreal* stateIm = qureg.stateVec.imag;
+
4462 
+
4463  // thread-private vars
+
4464  long long int index, globalAmpInd;
+
4465  int r, q, i, found, flatInd;
+
4466  qreal phase, norm, prod, dist, c, s, re, im;
+
4467 
+
4468  // each thread has a private static array of length >= numRegs (private var-length is illegal)
+
4469  long long int phaseInds[MAX_NUM_REGS_APPLY_ARBITRARY_PHASE];
+
4470 
+
4471 # ifdef _OPENMP
+
4472 # pragma omp parallel \
+
4473  default (none) \
+
4474  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubitsPerReg,numRegs,encoding, phaseFuncName,params,numParams, overrideInds,overridePhases,numOverrides, conj) \
+
4475  private (index,globalAmpInd, r,q,i,flatInd, found, phaseInds,phase,norm,prod,dist, c,s,re,im)
+
4476 # endif
+
4477  {
+
4478 # ifdef _OPENMP
+
4479 # pragma omp for schedule (static)
+
4480 # endif
+
4481  for (index=0LL; index<numAmps; index++) {
+
4482 
+
4483  // determine global amplitude index
+
4484  globalAmpInd = chunkId * numAmps + index;
+
4485 
+
4486  // determine phase indices
+
4487  flatInd = 0;
+
4488  for (r=0; r<numRegs; r++) {
+
4489  phaseInds[r] = 0LL;
+
4490 
+
4491  if (encoding == UNSIGNED) {
+
4492  for (q=0; q<numQubitsPerReg[r]; q++)
+
4493  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd); // qubits[flatInd] ~ qubits[r][q]
+
4494  }
+
4495  else if (encoding == TWOS_COMPLEMENT) {
+
4496  for (q=0; q<numQubitsPerReg[r]-1; q++)
+
4497  phaseInds[r] += (1LL << q) * extractBit(qubits[flatInd++], globalAmpInd);
+
4498  // use final qubit to indicate sign
+
4499  if (extractBit(qubits[flatInd++], globalAmpInd) == 1)
+
4500  phaseInds[r] -= (1LL << (numQubitsPerReg[r]-1));
+
4501  }
+
4502  }
+
4503 
+
4504  // determine if this phase index has an overriden value (i < numOverrides)
+
4505  for (i=0; i<numOverrides; i++) {
+
4506  found = 1;
+
4507  for (r=0; r<numRegs; r++) {
+
4508  if (phaseInds[r] != overrideInds[i*numRegs+r]) {
+
4509  found = 0;
+
4510  break;
+
4511  }
+
4512  }
+
4513  if (found)
+
4514  break;
+
4515  }
+
4516 
+
4517  // compute the phase (unless overriden)
+
4518  phase = 0;
+
4519  if (i < numOverrides)
+
4520  phase = overridePhases[i];
+
4521  else {
+
4522  // compute norm related phases
+
4523  if (phaseFuncName == NORM || phaseFuncName == INVERSE_NORM ||
+
4524  phaseFuncName == SCALED_NORM || phaseFuncName == SCALED_INVERSE_NORM ||
+
4525  phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
4526 
+
4527  norm = 0;
+
4528  if (phaseFuncName == SCALED_INVERSE_SHIFTED_NORM) {
+
4529  for (r=0; r<numRegs; r++)
+
4530  norm += (phaseInds[r] - params[2+r])*(phaseInds[r] - params[2+r]);
+
4531  }
+
4532  else
+
4533  for (r=0; r<numRegs; r++)
+
4534  norm += phaseInds[r]*phaseInds[r];
+
4535  norm = sqrt(norm);
+
4536 
+
4537  if (phaseFuncName == NORM)
+
4538  phase = norm;
+
4539  else if (phaseFuncName == INVERSE_NORM)
+
4540  phase = (norm == 0.)? params[0] : 1/norm; // smallest non-zero norm is 1
+
4541  else if (phaseFuncName == SCALED_NORM)
+
4542  phase = params[0] * norm;
+
4543  else if (phaseFuncName == SCALED_INVERSE_NORM || phaseFuncName == SCALED_INVERSE_SHIFTED_NORM)
+
4544  phase = (norm <= REAL_EPS)? params[1] : params[0] / norm; // unless shifted closer to zero
+
4545  }
+
4546  // compute product related phases
+
4547  else if (phaseFuncName == PRODUCT || phaseFuncName == INVERSE_PRODUCT ||
+
4548  phaseFuncName == SCALED_PRODUCT || phaseFuncName == SCALED_INVERSE_PRODUCT) {
+
4549 
+
4550  prod = 1;
+
4551  for (r=0; r<numRegs; r++)
+
4552  prod *= phaseInds[r];
+
4553 
+
4554  if (phaseFuncName == PRODUCT)
+
4555  phase = prod;
+
4556  else if (phaseFuncName == INVERSE_PRODUCT)
+
4557  phase = (prod == 0.)? params[0] : 1/prod; // smallest non-zero product norm is +- 1
+
4558  else if (phaseFuncName == SCALED_PRODUCT)
+
4559  phase = params[0] * prod;
+
4560  else if (phaseFuncName == SCALED_INVERSE_PRODUCT)
+
4561  phase = (prod == 0.)? params[1] : params[0] / prod;
+
4562  }
+
4563  // compute Euclidean distance related phases
+
4564  else if (phaseFuncName == DISTANCE || phaseFuncName == INVERSE_DISTANCE ||
+
4565  phaseFuncName == SCALED_DISTANCE || phaseFuncName == SCALED_INVERSE_DISTANCE ||
+
4566  phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
4567 
+
4568  dist = 0;
+
4569  if (phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE) {
+
4570  for (r=0; r<numRegs; r+=2)
+
4571  dist += (phaseInds[r] - phaseInds[r+1] - params[2+r/2])*(phaseInds[r] - phaseInds[r+1] - params[2+r/2]);
+
4572  }
+
4573  else
+
4574  for (r=0; r<numRegs; r+=2)
+
4575  dist += (phaseInds[r+1] - phaseInds[r])*(phaseInds[r+1] - phaseInds[r]);
+
4576  dist = sqrt(dist);
+
4577 
+
4578  if (phaseFuncName == DISTANCE)
+
4579  phase = dist;
+
4580  else if (phaseFuncName == INVERSE_DISTANCE)
+
4581  phase = (dist == 0.)? params[0] : 1/dist; // smallest non-zero dist is 1
+
4582  else if (phaseFuncName == SCALED_DISTANCE)
+
4583  phase = params[0] * dist;
+
4584  else if (phaseFuncName == SCALED_INVERSE_DISTANCE || phaseFuncName == SCALED_INVERSE_SHIFTED_DISTANCE)
+
4585  phase = (dist <= REAL_EPS)? params[1] : params[0] / dist; // unless shifted closer to 0
+
4586  }
+
4587  }
+
4588 
+
4589  // negate phase to conjugate operator
+
4590  if (conj)
+
4591  phase *= -1;
+
4592 
+
4593  // modify amp to amp * exp(i phase)
+
4594  c = cos(phase);
+
4595  s = sin(phase);
+
4596  re = stateRe[index];
+
4597  im = stateIm[index];
+
4598 
+
4599  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4600  stateRe[index] = re*c - im*s;
+
4601  stateIm[index] = re*s + im*c;
+
4602  }
+
4603  }
+
4604 }

References Qureg::chunkId, DISTANCE, extractBit(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, Qureg::numAmpsPerChunk, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, Qureg::stateVec, TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -3498,33 +3523,33 @@

-

Definition at line 548 of file QuEST_common.c.

-
548  {
-
549 
-
550  int numQb = inQureg.numQubitsRepresented;
-
551  int targs[numQb];
-
552  for (int q=0; q < numQb; q++)
-
553  targs[q] = q;
-
554 
-
555  statevec_initBlankState(outQureg);
-
556 
-
557  for (int t=0; t < numSumTerms; t++) {
-
558  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
-
559  Complex iden = (Complex) {.real=1, .imag=0};
-
560  Complex zero = (Complex) {.real=0, .imag=0};
-
561 
-
562  // outQureg += coef paulis(inQureg)
-
563  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
564  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
-
565 
-
566  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
-
567  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
-
568  }
-
569 }
+

Definition at line 538 of file QuEST_common.c.

+
538  {
+
539 
+
540  int numQb = inQureg.numQubitsRepresented;
+
541  int targs[100]; // [numQb];
+
542  for (int q=0; q < numQb; q++)
+
543  targs[q] = q;
+
544 
+
545  statevec_initBlankState(outQureg);
+
546 
+
547  for (int t=0; t < numSumTerms; t++) {
+
548  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
+
549  Complex iden = (Complex) {.real=1, .imag=0};
+
550  Complex zero = (Complex) {.real=0, .imag=0};
+
551 
+
552  // outQureg += coef paulis(inQureg)
+
553  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
+
554  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
+
555 
+
556  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
+
557  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
+
558  }
+
559 }
-

References Qureg::numQubitsRepresented, Complex::real, statevec_applyPauliProd(), statevec_initBlankState(), and statevec_setWeightedQureg().

+

References Qureg::numQubitsRepresented, Complex::real, statevec_applyPauliProd(), statevec_initBlankState(), and statevec_setWeightedQureg().

-

Referenced by applyPauliHamil(), and applyPauliSum().

+

Referenced by applyPauliHamil(), and applyPauliSum().

@@ -3608,82 +3633,82 @@

-

Definition at line 4228 of file QuEST_cpu.c.

-
4233 {
-
4234  // each node/chunk modifies only local values in an embarrassingly parallel way
-
4235 
-
4236  // thread shared vars
-
4237  int chunkId = qureg.chunkId;
-
4238  long long int numAmps = qureg.numAmpsPerChunk;
-
4239  qreal* stateRe = qureg.stateVec.real;
-
4240  qreal* stateIm = qureg.stateVec.imag;
-
4241 
-
4242  // thread private vars
-
4243  long long int index, globalAmpInd, phaseInd;
-
4244  int i, t, q;
-
4245  qreal phase, c, s, re, im;
-
4246 
-
4247 # ifdef _OPENMP
-
4248 # pragma omp parallel \
-
4249  default (none) \
-
4250  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubits,encoding, coeffs,exponents,numTerms, overrideInds,overridePhases,numOverrides, conj) \
-
4251  private (index, globalAmpInd, phaseInd, i,t,q, phase, c,s,re,im)
-
4252 # endif
-
4253  {
-
4254 # ifdef _OPENMP
-
4255 # pragma omp for schedule (static)
-
4256 # endif
-
4257  for (index=0LL; index<numAmps; index++) {
-
4258 
-
4259  // determine global amplitude index
-
4260  globalAmpInd = chunkId * numAmps + index;
-
4261 
-
4262  // determine phase index of {qubits}
-
4263  phaseInd = 0LL;
-
4264  if (encoding == UNSIGNED) {
-
4265  for (q=0; q<numQubits; q++) // use significance order specified by {qubits}
-
4266  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
4267  }
-
4268  else if (encoding == TWOS_COMPLEMENT) {
-
4269  for (q=0; q<numQubits-1; q++) // use final qubit to indicate sign
-
4270  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
-
4271  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
-
4272  phaseInd -= (1LL << (numQubits-1));
-
4273  }
-
4274 
-
4275  // determine if this phase index has an overriden value (i < numOverrides)
-
4276  for (i=0; i<numOverrides; i++)
-
4277  if (phaseInd == overrideInds[i])
-
4278  break;
-
4279 
-
4280  // determine phase from {coeffs}, {exponents} (unless overriden)
-
4281  phase = 0;
-
4282  if (i < numOverrides)
-
4283  phase = overridePhases[i];
-
4284  else
-
4285  for (t=0; t<numTerms; t++)
-
4286  phase += coeffs[t] * pow(phaseInd, exponents[t]);
-
4287 
-
4288  // negate phase to conjugate operator
-
4289  if (conj)
-
4290  phase *= -1;
-
4291 
-
4292  // modify amp to amp * exp(i phase)
-
4293  c = cos(phase);
-
4294  s = sin(phase);
-
4295  re = stateRe[index];
-
4296  im = stateIm[index];
-
4297 
-
4298  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
-
4299  stateRe[index] = re*c - im*s;
-
4300  stateIm[index] = re*s + im*c;
-
4301  }
-
4302  }
-
4303 }
+

Definition at line 4268 of file QuEST_cpu.c.

+
4273 {
+
4274  // each node/chunk modifies only local values in an embarrassingly parallel way
+
4275 
+
4276  // thread shared vars
+
4277  int chunkId = qureg.chunkId;
+
4278  long long int numAmps = qureg.numAmpsPerChunk;
+
4279  qreal* stateRe = qureg.stateVec.real;
+
4280  qreal* stateIm = qureg.stateVec.imag;
+
4281 
+
4282  // thread private vars
+
4283  long long int index, globalAmpInd, phaseInd;
+
4284  int i, t, q;
+
4285  qreal phase, c, s, re, im;
+
4286 
+
4287 # ifdef _OPENMP
+
4288 # pragma omp parallel \
+
4289  default (none) \
+
4290  shared (chunkId,numAmps, stateRe,stateIm, qubits,numQubits,encoding, coeffs,exponents,numTerms, overrideInds,overridePhases,numOverrides, conj) \
+
4291  private (index, globalAmpInd, phaseInd, i,t,q, phase, c,s,re,im)
+
4292 # endif
+
4293  {
+
4294 # ifdef _OPENMP
+
4295 # pragma omp for schedule (static)
+
4296 # endif
+
4297  for (index=0LL; index<numAmps; index++) {
+
4298 
+
4299  // determine global amplitude index
+
4300  globalAmpInd = chunkId * numAmps + index;
+
4301 
+
4302  // determine phase index of {qubits}
+
4303  phaseInd = 0LL;
+
4304  if (encoding == UNSIGNED) {
+
4305  for (q=0; q<numQubits; q++) // use significance order specified by {qubits}
+
4306  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
4307  }
+
4308  else if (encoding == TWOS_COMPLEMENT) {
+
4309  for (q=0; q<numQubits-1; q++) // use final qubit to indicate sign
+
4310  phaseInd += (1LL << q) * extractBit(qubits[q], globalAmpInd);
+
4311  if (extractBit(qubits[numQubits-1], globalAmpInd) == 1)
+
4312  phaseInd -= (1LL << (numQubits-1));
+
4313  }
+
4314 
+
4315  // determine if this phase index has an overriden value (i < numOverrides)
+
4316  for (i=0; i<numOverrides; i++)
+
4317  if (phaseInd == overrideInds[i])
+
4318  break;
+
4319 
+
4320  // determine phase from {coeffs}, {exponents} (unless overriden)
+
4321  phase = 0;
+
4322  if (i < numOverrides)
+
4323  phase = overridePhases[i];
+
4324  else
+
4325  for (t=0; t<numTerms; t++)
+
4326  phase += coeffs[t] * pow(phaseInd, exponents[t]);
+
4327 
+
4328  // negate phase to conjugate operator
+
4329  if (conj)
+
4330  phase *= -1;
+
4331 
+
4332  // modify amp to amp * exp(i phase)
+
4333  c = cos(phase);
+
4334  s = sin(phase);
+
4335  re = stateRe[index];
+
4336  im = stateIm[index];
+
4337 
+
4338  // = {re[amp] cos(phase) - im[amp] sin(phase)} + i {re[amp] sin(phase) + im[amp] cos(phase)}
+
4339  stateRe[index] = re*c - im*s;
+
4340  stateIm[index] = re*s + im*c;
+
4341  }
+
4342  }
+
4343 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -3713,28 +3738,28 @@

-

Definition at line 1589 of file QuEST_cpu_distributed.c.

-
1589  {
-
1590 
-
1591  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
-
1592  if (qureg.numChunks == 1)
-
1593  return localExpec;
-
1594 
-
1595  qreal localReal = localExpec.real;
-
1596  qreal localImag = localExpec.imag;
-
1597  qreal globalReal, globalImag;
-
1598  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1599  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1600 
-
1601  Complex globalExpec;
-
1602  globalExpec.real = globalReal;
-
1603  globalExpec.imag = globalImag;
-
1604  return globalExpec;
-
1605 }
+

Definition at line 1600 of file QuEST_cpu_distributed.c.

+
1600  {
+
1601 
+
1602  Complex localExpec = statevec_calcExpecDiagonalOpLocal(qureg, op);
+
1603  if (qureg.numChunks == 1)
+
1604  return localExpec;
+
1605 
+
1606  qreal localReal = localExpec.real;
+
1607  qreal localImag = localExpec.imag;
+
1608  qreal globalReal, globalImag;
+
1609  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1610  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1611 
+
1612  Complex globalExpec;
+
1613  globalExpec.real = globalReal;
+
1614  globalExpec.imag = globalImag;
+
1615  return globalExpec;
+
1616 }
-

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, statevec_calcExpecDiagonalOpLocal(), and swapDouble().

+

References copySharedReduceBlock(), DiagonalOp::deviceOperator, Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, statevec_calcExpecDiagonalOpLocal(), and swapDouble().

-

Referenced by calcExpecDiagonalOp().

+

Referenced by calcExpecDiagonalOp().

@@ -3782,25 +3807,25 @@

-

Definition at line 519 of file QuEST_common.c.

-
519  {
-
520 
-
521  statevec_cloneQureg(workspace, qureg);
-
522  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
-
523 
-
524  // compute the expected value
-
525  qreal value;
-
526  if (qureg.isDensityMatrix)
-
527  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
-
528  else
-
529  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
-
530 
-
531  return value;
-
532 }
+

Definition at line 509 of file QuEST_common.c.

+
509  {
+
510 
+
511  statevec_cloneQureg(workspace, qureg);
+
512  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
+
513 
+
514  // compute the expected value
+
515  qreal value;
+
516  if (qureg.isDensityMatrix)
+
517  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
+
518  else
+
519  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
+
520 
+
521  return value;
+
522 }
-

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, qreal, Complex::real, statevec_applyPauliProd(), statevec_calcInnerProduct(), and statevec_cloneQureg().

+

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, qreal, Complex::real, statevec_applyPauliProd(), statevec_calcInnerProduct(), and statevec_cloneQureg().

-

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

+

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

@@ -3848,24 +3873,24 @@

-

Definition at line 534 of file QuEST_common.c.

-
534  {
-
535 
-
536  int numQb = qureg.numQubitsRepresented;
-
537  int targs[numQb];
-
538  for (int q=0; q < numQb; q++)
-
539  targs[q] = q;
-
540 
-
541  qreal value = 0;
-
542  for (int t=0; t < numSumTerms; t++)
-
543  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
-
544 
-
545  return value;
-
546 }
+

Definition at line 524 of file QuEST_common.c.

+
524  {
+
525 
+
526  int numQb = qureg.numQubitsRepresented;
+
527  int targs[100]; // [numQb];
+
528  for (int q=0; q < numQb; q++)
+
529  targs[q] = q;
+
530 
+
531  qreal value = 0;
+
532  for (int t=0; t < numSumTerms; t++)
+
533  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
+
534 
+
535  return value;
+
536 }
-

References Qureg::numQubitsRepresented, qreal, and statevec_calcExpecPauliProd().

+

References Qureg::numQubitsRepresented, qreal, and statevec_calcExpecPauliProd().

-

Referenced by calcExpecPauliHamil(), and calcExpecPauliSum().

+

Referenced by calcExpecPauliHamil(), and calcExpecPauliSum().

@@ -3895,17 +3920,17 @@

-

Definition at line 390 of file QuEST_common.c.

-
390  {
-
391 
-
392  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
-
393  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
-
394  return innerProdMag;
-
395 }
+

Definition at line 380 of file QuEST_common.c.

+
380  {
+
381 
+
382  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
+
383  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
+
384  return innerProdMag;
+
385 }

References Complex::imag, qreal, Complex::real, and statevec_calcInnerProduct().

-

Referenced by calcFidelity().

+

Referenced by calcFidelity().

@@ -3957,9 +3982,9 @@

50  return globalInnerProd;
51 }
-

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, statevec_calcInnerProductLocal(), and swapDouble().

+

References copySharedReduceBlock(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Complex::imag, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Complex::real, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, statevec_calcInnerProductLocal(), and swapDouble().

-

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

+

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

@@ -4001,19 +4026,19 @@

-

Definition at line 1336 of file QuEST_cpu_distributed.c.

-
1336  {
-
1337 
-
1338  // each node populates retProbs with contributions from the subset of amps in each
-
1339  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
-
1340 
-
1341  // then, retProbs are summed element-wise
-
1342  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1343 }
+

Definition at line 1340 of file QuEST_cpu_distributed.c.

+
1340  {
+
1341 
+
1342  // each node populates retProbs with contributions from the subset of amps in each
+
1343  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
+
1344 
+
1345  // then, retProbs are summed element-wise
+
1346  MPI_Allreduce(MPI_IN_PLACE, retProbs, 1LL<<numQubits, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1347 }
-

References Qureg::numAmpsPerChunk, qreal, and statevec_calcProbOfAllOutcomesLocal().

+

References Qureg::numAmpsPerChunk, qreal, and statevec_calcProbOfAllOutcomesLocal().

-

Referenced by calcProbOfAllOutcomes().

+

Referenced by calcProbOfAllOutcomes().

@@ -4049,25 +4074,25 @@

-

Definition at line 1308 of file QuEST_cpu_distributed.c.

-
1309 {
-
1310  qreal stateProb=0, totalStateProb=0;
-
1311  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1312  if (skipValuesWithinRank) {
-
1313  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
-
1314  } else {
-
1315  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1316  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
-
1317  } else stateProb = 0;
-
1318  }
-
1319  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
-
1320  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
-
1321  return totalStateProb;
-
1322 }
+

Definition at line 1312 of file QuEST_cpu_distributed.c.

+
1313 {
+
1314  qreal stateProb=0, totalStateProb=0;
+
1315  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
+
1316  if (skipValuesWithinRank) {
+
1317  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
+
1318  } else {
+
1319  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
+
1320  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
+
1321  } else stateProb = 0;
+
1322  }
+
1323  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
+
1324  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
+
1325  return totalStateProb;
+
1326 }
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_findProbabilityOfZero(), statevec_findProbabilityOfZeroDistributed(), and statevec_findProbabilityOfZeroLocal().

+

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_findProbabilityOfZero(), statevec_findProbabilityOfZeroDistributed(), and statevec_findProbabilityOfZeroLocal().

-

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

+

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

@@ -4119,9 +4144,9 @@

116  return allRankTotals;
117 }
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

+

References copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

-

Referenced by calcTotalProb().

+

Referenced by calcTotalProb().

@@ -4153,43 +4178,43 @@

Definition at line 1561 of file QuEST_cpu.c.

-
1561  {
-
1562 
-
1563  // registers are equal sized, so nodes hold the same state-vector partitions
-
1564  long long int stateVecSize;
-
1565  long long int index;
-
1566 
-
1567  // dimension of the state vector
-
1568  stateVecSize = targetQureg.numAmpsPerChunk;
-
1569 
-
1570  // Can't use qureg->stateVec as a private OMP var
-
1571  qreal *targetStateVecReal = targetQureg.stateVec.real;
-
1572  qreal *targetStateVecImag = targetQureg.stateVec.imag;
-
1573  qreal *copyStateVecReal = copyQureg.stateVec.real;
-
1574  qreal *copyStateVecImag = copyQureg.stateVec.imag;
-
1575 
-
1576  // initialise the state to |0000..0000>
-
1577 # ifdef _OPENMP
-
1578 # pragma omp parallel \
-
1579  default (none) \
-
1580  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
-
1581  private (index)
-
1582 # endif
-
1583  {
-
1584 # ifdef _OPENMP
-
1585 # pragma omp for schedule (static)
-
1586 # endif
-
1587  for (index=0; index<stateVecSize; index++) {
-
1588  targetStateVecReal[index] = copyStateVecReal[index];
-
1589  targetStateVecImag[index] = copyStateVecImag[index];
-
1590  }
-
1591  }
-
1592 }
+

Definition at line 1572 of file QuEST_cpu.c.

+
1572  {
+
1573 
+
1574  // registers are equal sized, so nodes hold the same state-vector partitions
+
1575  long long int stateVecSize;
+
1576  long long int index;
+
1577 
+
1578  // dimension of the state vector
+
1579  stateVecSize = targetQureg.numAmpsPerChunk;
+
1580 
+
1581  // Can't use qureg->stateVec as a private OMP var
+
1582  qreal *targetStateVecReal = targetQureg.stateVec.real;
+
1583  qreal *targetStateVecImag = targetQureg.stateVec.imag;
+
1584  qreal *copyStateVecReal = copyQureg.stateVec.real;
+
1585  qreal *copyStateVecImag = copyQureg.stateVec.imag;
+
1586 
+
1587  // initialise the state to |0000..0000>
+
1588 # ifdef _OPENMP
+
1589 # pragma omp parallel \
+
1590  default (none) \
+
1591  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
+
1592  private (index)
+
1593 # endif
+
1594  {
+
1595 # ifdef _OPENMP
+
1596 # pragma omp for schedule (static)
+
1597 # endif
+
1598  for (index=0; index<stateVecSize; index++) {
+
1599  targetStateVecReal[index] = copyStateVecReal[index];
+
1600  targetStateVecImag[index] = copyStateVecImag[index];
+
1601  }
+
1602  }
+
1603 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

+

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

@@ -4231,29 +4256,29 @@

-

Definition at line 1364 of file QuEST_cpu_distributed.c.

-
1365 {
-
1366  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
-
1367  if (skipValuesWithinRank) {
-
1368  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
-
1369  } else {
-
1370  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
-
1371  // chunk has amps for q=0
-
1372  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1373  totalStateProb);
- -
1375  } else {
-
1376  // chunk has amps for q=1
-
1377  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
-
1378  totalStateProb);
- -
1380  }
-
1381  }
-
1382 }
+

Definition at line 1368 of file QuEST_cpu_distributed.c.

+
1369 {
+
1370  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
+
1371  if (skipValuesWithinRank) {
+
1372  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
+
1373  } else {
+
1374  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
+
1375  // chunk has amps for q=0
+
1376  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
+
1377  totalStateProb);
+ +
1379  } else {
+
1380  // chunk has amps for q=1
+
1381  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
+
1382  totalStateProb);
+ +
1384  }
+
1385  }
+
1386 }
-

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), and statevec_collapseToOutcomeDistributedSetZero().

+

References Qureg::chunkId, halfMatrixBlockFitsInChunk(), isChunkToSkipInFindPZero(), Qureg::numAmpsPerChunk, qreal, statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), and statevec_collapseToOutcomeDistributedSetZero().

-

Referenced by collapseToOutcome(), and statevec_measureWithStats().

+

Referenced by applyProjector(), collapseToOutcome(), and statevec_measureWithStats().

@@ -4295,46 +4320,46 @@

-

Definition at line 854 of file QuEST_cpu_distributed.c.

-
855 {
-
856  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
857  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
858  Complex rot1, rot2;
-
859 
-
860  // rank's chunk is in upper half of block
-
861  int rankIsUpper;
-
862  int pairRank; // rank of corresponding chunk
+

Definition at line 858 of file QuEST_cpu_distributed.c.

+
859 {
+
860  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
861  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
862  Complex rot1, rot2;
863 
-
864  if (useLocalDataOnly){
-
865  // all values required to update state vector lie in this rank
-
866  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
-
867  } else {
-
868  // need to get corresponding chunk of state vector from other rank
-
869  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
870  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
871  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
872  // get corresponding values from my pair
-
873  exchangeStateVectors(qureg, pairRank);
-
874 
-
875  // this rank's values are either in the upper of lower half of the block.
-
876  // send values to compactUnitaryDistributed in the correct order
-
877  if (rankIsUpper){
-
878  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
879  qureg.stateVec, //upper
-
880  qureg.pairStateVec, //lower
-
881  qureg.stateVec); //output
-
882  } else {
-
883  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
-
884  qureg.pairStateVec, //upper
-
885  qureg.stateVec, //lower
-
886  qureg.stateVec); //output
-
887  }
-
888  }
-
889 }
+
864  // rank's chunk is in upper half of block
+
865  int rankIsUpper;
+
866  int pairRank; // rank of corresponding chunk
+
867 
+
868  if (useLocalDataOnly){
+
869  // all values required to update state vector lie in this rank
+
870  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
+
871  } else {
+
872  // need to get corresponding chunk of state vector from other rank
+
873  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
874  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
+
875  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
876  // get corresponding values from my pair
+
877  exchangeStateVectors(qureg, pairRank);
+
878 
+
879  // this rank's values are either in the upper of lower half of the block.
+
880  // send values to compactUnitaryDistributed in the correct order
+
881  if (rankIsUpper){
+
882  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
+
883  qureg.stateVec, //upper
+
884  qureg.pairStateVec, //lower
+
885  qureg.stateVec); //output
+
886  } else {
+
887  statevec_compactUnitaryDistributed(qureg,rot1,rot2,
+
888  qureg.pairStateVec, //upper
+
889  qureg.stateVec, //lower
+
890  qureg.stateVec); //output
+
891  }
+
892  }
+
893 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_compactUnitaryDistributed(), and statevec_compactUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_compactUnitaryDistributed(), and statevec_compactUnitaryLocal().

-

Referenced by compactUnitary(), statevec_multiRotatePauli(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

+

Referenced by compactUnitary(), statevec_multiRotatePauli(), statevec_rotateAroundAxis(), and statevec_rotateAroundAxisConj().

@@ -4370,23 +4395,23 @@

-

Definition at line 1730 of file QuEST_cpu.c.

-
1730  {
-
1731  qreal diff;
-
1732  long long int chunkSize = mq1.numAmpsPerChunk;
-
1733 
-
1734  for (long long int i=0; i<chunkSize; i++){
-
1735  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
-
1736  if (diff>precision) return 0;
-
1737  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
-
1738  if (diff>precision) return 0;
-
1739  }
-
1740  return 1;
-
1741 }
+

Definition at line 1741 of file QuEST_cpu.c.

+
1741  {
+
1742  qreal diff;
+
1743  long long int chunkSize = mq1.numAmpsPerChunk;
+
1744 
+
1745  for (long long int i=0; i<chunkSize; i++){
+
1746  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
+
1747  if (diff>precision) return 0;
+
1748  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
+
1749  if (diff>precision) return 0;
+
1750  }
+
1751  return 1;
+
1752 }
-

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by compareStates().

+

Referenced by compareStates().

@@ -4434,47 +4459,47 @@

-

Definition at line 930 of file QuEST_cpu_distributed.c.

-
931 {
-
932  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
933  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
934  Complex rot1, rot2;
-
935 
-
936  // rank's chunk is in upper half of block
-
937  int rankIsUpper;
-
938  int pairRank; // rank of corresponding chunk
+

Definition at line 934 of file QuEST_cpu_distributed.c.

+
935 {
+
936  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
937  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
938  Complex rot1, rot2;
939 
-
940  if (useLocalDataOnly){
-
941  // all values required to update state vector lie in this rank
-
942  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
-
943  } else {
-
944  // need to get corresponding chunk of state vector from other rank
-
945  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
946  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
-
947  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
948  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
949  // get corresponding values from my pair
-
950  exchangeStateVectors(qureg, pairRank);
-
951 
-
952  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
-
953  // in the correct order
-
954  if (rankIsUpper){
-
955  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
956  qureg.stateVec, //upper
-
957  qureg.pairStateVec, //lower
-
958  qureg.stateVec); //output
-
959  } else {
-
960  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
961  qureg.pairStateVec, //upper
-
962  qureg.stateVec, //lower
-
963  qureg.stateVec); //output
-
964  }
-
965  }
-
966 }
+
940  // rank's chunk is in upper half of block
+
941  int rankIsUpper;
+
942  int pairRank; // rank of corresponding chunk
+
943 
+
944  if (useLocalDataOnly){
+
945  // all values required to update state vector lie in this rank
+
946  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
+
947  } else {
+
948  // need to get corresponding chunk of state vector from other rank
+
949  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
950  getRotAngle(rankIsUpper, &rot1, &rot2, alpha, beta);
+
951  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
952  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
953  // get corresponding values from my pair
+
954  exchangeStateVectors(qureg, pairRank);
+
955 
+
956  // this rank's values are either in the upper of lower half of the block. send values to controlledCompactUnitaryDistributed
+
957  // in the correct order
+
958  if (rankIsUpper){
+
959  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
960  qureg.stateVec, //upper
+
961  qureg.pairStateVec, //lower
+
962  qureg.stateVec); //output
+
963  } else {
+
964  statevec_controlledCompactUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
965  qureg.pairStateVec, //upper
+
966  qureg.stateVec, //lower
+
967  qureg.stateVec); //output
+
968  }
+
969  }
+
970 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledCompactUnitaryDistributed(), and statevec_controlledCompactUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngle(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledCompactUnitaryDistributed(), and statevec_controlledCompactUnitaryLocal().

-

Referenced by controlledCompactUnitary(), statevec_controlledRotateAroundAxis(), and statevec_controlledRotateAroundAxisConj().

+

Referenced by controlledCompactUnitary(), statevec_controlledRotateAroundAxis(), and statevec_controlledRotateAroundAxisConj().

@@ -4522,16 +4547,16 @@

-

Definition at line 589 of file QuEST_common.c.

-
589  {
-
590 
-
591  long long int ctrlMask = 1LL << ctrl;
-
592  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
593 }
+

Definition at line 579 of file QuEST_common.c.

+
579  {
+
580 
+
581  long long int ctrlMask = 1LL << ctrl;
+
582  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
+
583 }
-

References statevec_multiControlledMultiQubitUnitary().

+

References statevec_multiControlledMultiQubitUnitary().

-

Referenced by controlledMultiQubitUnitary().

+

Referenced by controlledMultiQubitUnitary().

@@ -4567,31 +4592,31 @@

-

Definition at line 1071 of file QuEST_cpu_distributed.c.

-
1072 {
-
1073  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1074  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1075  int rankIsUpper; // rank's chunk is in upper half of block
-
1076  int pairRank; // rank of corresponding chunk
-
1077 
-
1078  if (useLocalDataOnly){
-
1079  // all values required to update state vector lie in this rank
-
1080  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
-
1081  } else {
-
1082  // need to get corresponding chunk of state vector from other rank
-
1083  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1084  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1085  // get corresponding values from my pair
-
1086  exchangeStateVectors(qureg, pairRank);
-
1087  statevec_controlledNotDistributed(qureg,controlQubit,
-
1088  qureg.pairStateVec, //in
-
1089  qureg.stateVec); //out
-
1090  }
-
1091 }
+

Definition at line 1075 of file QuEST_cpu_distributed.c.

+
1076 {
+
1077  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1078  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1079  int rankIsUpper; // rank's chunk is in upper half of block
+
1080  int pairRank; // rank of corresponding chunk
+
1081 
+
1082  if (useLocalDataOnly){
+
1083  // all values required to update state vector lie in this rank
+
1084  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
+
1085  } else {
+
1086  // need to get corresponding chunk of state vector from other rank
+
1087  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1088  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1089  // get corresponding values from my pair
+
1090  exchangeStateVectors(qureg, pairRank);
+
1091  statevec_controlledNotDistributed(qureg,controlQubit,
+
1092  qureg.pairStateVec, //in
+
1093  qureg.stateVec); //out
+
1094  }
+
1095 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledNotDistributed(), and statevec_controlledNotLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledNotDistributed(), and statevec_controlledNotLocal().

-

Referenced by controlledNot().

+

Referenced by controlledNot().

@@ -4627,42 +4652,42 @@

-

Definition at line 1188 of file QuEST_cpu_distributed.c.

-
1189 {
-
1190  int conjFac = 1;
-
1191 
-
1192  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1193  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1194  int rankIsUpper; // rank's chunk is in upper half of block
-
1195  int pairRank; // rank of corresponding chunk
-
1196 
-
1197  if (useLocalDataOnly){
-
1198  // all values required to update state vector lie in this rank
-
1199  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1200  } else {
-
1201  // need to get corresponding chunk of state vector from other rank
-
1202  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1203  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1204  // get corresponding values from my pair
-
1205  exchangeStateVectors(qureg, pairRank);
-
1206  // this rank's values are either in the upper of lower half of the block
-
1207  if (rankIsUpper){
-
1208  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1209  qureg.pairStateVec, //in
-
1210  qureg.stateVec,
-
1211  conjFac); //out
-
1212  } else {
-
1213  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1214  qureg.pairStateVec, //in
-
1215  qureg.stateVec,
-
1216  - conjFac); //out
-
1217  }
-
1218  }
-
1219 }
+

Definition at line 1192 of file QuEST_cpu_distributed.c.

+
1193 {
+
1194  int conjFac = 1;
+
1195 
+
1196  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1197  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1198  int rankIsUpper; // rank's chunk is in upper half of block
+
1199  int pairRank; // rank of corresponding chunk
+
1200 
+
1201  if (useLocalDataOnly){
+
1202  // all values required to update state vector lie in this rank
+
1203  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
1204  } else {
+
1205  // need to get corresponding chunk of state vector from other rank
+
1206  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1207  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1208  // get corresponding values from my pair
+
1209  exchangeStateVectors(qureg, pairRank);
+
1210  // this rank's values are either in the upper of lower half of the block
+
1211  if (rankIsUpper){
+
1212  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1213  qureg.pairStateVec, //in
+
1214  qureg.stateVec,
+
1215  conjFac); //out
+
1216  } else {
+
1217  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1218  qureg.pairStateVec, //in
+
1219  qureg.stateVec,
+
1220  - conjFac); //out
+
1221  }
+
1222  }
+
1223 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

-

Referenced by controlledPauliY().

+

Referenced by controlledPauliY().

@@ -4698,42 +4723,42 @@

-

Definition at line 1221 of file QuEST_cpu_distributed.c.

-
1222 {
-
1223  int conjFac = -1;
-
1224 
-
1225  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1226  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1227  int rankIsUpper; // rank's chunk is in upper half of block
-
1228  int pairRank; // rank of corresponding chunk
-
1229 
-
1230  if (useLocalDataOnly){
-
1231  // all values required to update state vector lie in this rank
-
1232  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
-
1233  } else {
-
1234  // need to get corresponding chunk of state vector from other rank
-
1235  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1236  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1237  // get corresponding values from my pair
-
1238  exchangeStateVectors(qureg, pairRank);
-
1239  // this rank's values are either in the upper of lower half of the block
-
1240  if (rankIsUpper){
-
1241  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1242  qureg.pairStateVec, //in
-
1243  qureg.stateVec,
-
1244  conjFac); //out
-
1245  } else {
-
1246  statevec_controlledPauliYDistributed(qureg,controlQubit,
-
1247  qureg.pairStateVec, //in
-
1248  qureg.stateVec,
-
1249  - conjFac); //out
-
1250  }
-
1251  }
-
1252 }
+

Definition at line 1225 of file QuEST_cpu_distributed.c.

+
1226 {
+
1227  int conjFac = -1;
+
1228 
+
1229  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1230  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1231  int rankIsUpper; // rank's chunk is in upper half of block
+
1232  int pairRank; // rank of corresponding chunk
+
1233 
+
1234  if (useLocalDataOnly){
+
1235  // all values required to update state vector lie in this rank
+
1236  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
+
1237  } else {
+
1238  // need to get corresponding chunk of state vector from other rank
+
1239  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1240  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1241  // get corresponding values from my pair
+
1242  exchangeStateVectors(qureg, pairRank);
+
1243  // this rank's values are either in the upper of lower half of the block
+
1244  if (rankIsUpper){
+
1245  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1246  qureg.pairStateVec, //in
+
1247  qureg.stateVec,
+
1248  conjFac); //out
+
1249  } else {
+
1250  statevec_controlledPauliYDistributed(qureg,controlQubit,
+
1251  qureg.pairStateVec, //in
+
1252  qureg.stateVec,
+
1253  - conjFac); //out
+
1254  }
+
1255  }
+
1256 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

-

Referenced by controlledPauliY().

+

Referenced by controlledPauliY().

@@ -4769,40 +4794,40 @@

-

Definition at line 3647 of file QuEST_cpu.c.

-
3648 {
-
3649  long long int index;
-
3650  long long int stateVecSize;
-
3651  int bit1, bit2;
-
3652 
-
3653  long long int chunkSize=qureg.numAmpsPerChunk;
-
3654  long long int chunkId=qureg.chunkId;
-
3655 
-
3656  // dimension of the state vector
-
3657  stateVecSize = qureg.numAmpsPerChunk;
-
3658  qreal *stateVecReal = qureg.stateVec.real;
-
3659  qreal *stateVecImag = qureg.stateVec.imag;
-
3660 
-
3661 # ifdef _OPENMP
-
3662 # pragma omp parallel for \
-
3663  default (none) \
-
3664  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
-
3665  private (index,bit1,bit2) \
-
3666  schedule (static)
-
3667 # endif
-
3668  for (index=0; index<stateVecSize; index++) {
-
3669  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3670  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3671  if (bit1 && bit2) {
-
3672  stateVecReal [index] = - stateVecReal [index];
-
3673  stateVecImag [index] = - stateVecImag [index];
-
3674  }
-
3675  }
-
3676 }
+

Definition at line 3687 of file QuEST_cpu.c.

+
3688 {
+
3689  long long int index;
+
3690  long long int stateVecSize;
+
3691  int bit1, bit2;
+
3692 
+
3693  long long int chunkSize=qureg.numAmpsPerChunk;
+
3694  long long int chunkId=qureg.chunkId;
+
3695 
+
3696  // dimension of the state vector
+
3697  stateVecSize = qureg.numAmpsPerChunk;
+
3698  qreal *stateVecReal = qureg.stateVec.real;
+
3699  qreal *stateVecImag = qureg.stateVec.imag;
+
3700 
+
3701 # ifdef _OPENMP
+
3702 # pragma omp parallel for \
+
3703  default (none) \
+
3704  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize,idQubit1,idQubit2 ) \
+
3705  private (index,bit1,bit2) \
+
3706  schedule (static)
+
3707 # endif
+
3708  for (index=0; index<stateVecSize; index++) {
+
3709  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
+
3710  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
+
3711  if (bit1 && bit2) {
+
3712  stateVecReal [index] = - stateVecReal [index];
+
3713  stateVecImag [index] = - stateVecImag [index];
+
3714  }
+
3715  }
+
3716 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by controlledPhaseFlip().

+

Referenced by controlledPhaseFlip().

@@ -4844,49 +4869,49 @@

-

Definition at line 3187 of file QuEST_cpu.c.

-
3188 {
-
3189  long long int index;
-
3190  long long int stateVecSize;
-
3191  int bit1, bit2;
-
3192 
-
3193  long long int chunkSize=qureg.numAmpsPerChunk;
-
3194  long long int chunkId=qureg.chunkId;
-
3195 
-
3196  // dimension of the state vector
-
3197  stateVecSize = qureg.numAmpsPerChunk;
-
3198  qreal *stateVecReal = qureg.stateVec.real;
-
3199  qreal *stateVecImag = qureg.stateVec.imag;
-
3200 
-
3201  qreal stateRealLo, stateImagLo;
-
3202  qreal cosAngle = cos(angle);
-
3203  qreal sinAngle = sin(angle);
-
3204 
-
3205 # ifdef _OPENMP
-
3206 # pragma omp parallel for \
-
3207  default (none) \
-
3208  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
-
3209  idQubit1,idQubit2,cosAngle,sinAngle ) \
-
3210  private (index,bit1,bit2,stateRealLo,stateImagLo) \
-
3211  schedule (static)
-
3212 # endif
-
3213  for (index=0; index<stateVecSize; index++) {
-
3214  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
-
3215  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
-
3216  if (bit1 && bit2) {
-
3217 
-
3218  stateRealLo = stateVecReal[index];
-
3219  stateImagLo = stateVecImag[index];
-
3220 
-
3221  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3222  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3223  }
-
3224  }
-
3225 }
+

Definition at line 3226 of file QuEST_cpu.c.

+
3227 {
+
3228  long long int index;
+
3229  long long int stateVecSize;
+
3230  int bit1, bit2;
+
3231 
+
3232  long long int chunkSize=qureg.numAmpsPerChunk;
+
3233  long long int chunkId=qureg.chunkId;
+
3234 
+
3235  // dimension of the state vector
+
3236  stateVecSize = qureg.numAmpsPerChunk;
+
3237  qreal *stateVecReal = qureg.stateVec.real;
+
3238  qreal *stateVecImag = qureg.stateVec.imag;
+
3239 
+
3240  qreal stateRealLo, stateImagLo;
+
3241  qreal cosAngle = cos(angle);
+
3242  qreal sinAngle = sin(angle);
+
3243 
+
3244 # ifdef _OPENMP
+
3245 # pragma omp parallel for \
+
3246  default (none) \
+
3247  shared (stateVecSize, stateVecReal,stateVecImag, chunkId,chunkSize, \
+
3248  idQubit1,idQubit2,cosAngle,sinAngle ) \
+
3249  private (index,bit1,bit2,stateRealLo,stateImagLo) \
+
3250  schedule (static)
+
3251 # endif
+
3252  for (index=0; index<stateVecSize; index++) {
+
3253  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
+
3254  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
+
3255  if (bit1 && bit2) {
+
3256 
+
3257  stateRealLo = stateVecReal[index];
+
3258  stateImagLo = stateVecImag[index];
+
3259 
+
3260  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3261  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3262  }
+
3263  }
+
3264 }

References Qureg::chunkId, extractBit(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by controlledPhaseShift().

+

Referenced by controlledPhaseShift().

@@ -4934,17 +4959,17 @@

-

Definition at line 340 of file QuEST_common.c.

-
340  {
-
341 
-
342  Complex alpha, beta;
-
343  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
344  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
345 }
+

Definition at line 330 of file QuEST_common.c.

+
330  {
+
331 
+
332  Complex alpha, beta;
+
333  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
334  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
335 }
-

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

+

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

-

Referenced by controlledRotateAroundAxis(), statevec_controlledRotateX(), statevec_controlledRotateY(), and statevec_controlledRotateZ().

+

Referenced by controlledRotateAroundAxis(), statevec_controlledRotateX(), statevec_controlledRotateY(), and statevec_controlledRotateZ().

@@ -4992,19 +5017,19 @@

-

Definition at line 347 of file QuEST_common.c.

-
347  {
-
348 
-
349  Complex alpha, beta;
-
350  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
351  alpha.imag *= -1;
-
352  beta.imag *= -1;
-
353  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
-
354 }
+

Definition at line 337 of file QuEST_common.c.

+
337  {
+
338 
+
339  Complex alpha, beta;
+
340  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
341  alpha.imag *= -1;
+
342  beta.imag *= -1;
+
343  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
+
344 }
-

References getComplexPairFromRotation(), Complex::imag, and statevec_controlledCompactUnitary().

+

References getComplexPairFromRotation(), Complex::imag, and statevec_controlledCompactUnitary().

-

Referenced by controlledRotateAroundAxis().

+

Referenced by controlledRotateAroundAxis().

@@ -5046,16 +5071,16 @@

-

Definition at line 356 of file QuEST_common.c.

-
356  {
-
357 
-
358  Vector unitAxis = {1, 0, 0};
-
359  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
360 }
+

Definition at line 346 of file QuEST_common.c.

+
346  {
+
347 
+
348  Vector unitAxis = {1, 0, 0};
+
349  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
350 }
-

References statevec_controlledRotateAroundAxis().

+

References statevec_controlledRotateAroundAxis().

-

Referenced by controlledRotateX().

+

Referenced by controlledRotateX().

@@ -5097,16 +5122,16 @@

-

Definition at line 362 of file QuEST_common.c.

-
362  {
-
363 
-
364  Vector unitAxis = {0, 1, 0};
-
365  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
366 }
+

Definition at line 352 of file QuEST_common.c.

+
352  {
+
353 
+
354  Vector unitAxis = {0, 1, 0};
+
355  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
356 }
-

References statevec_controlledRotateAroundAxis().

+

References statevec_controlledRotateAroundAxis().

-

Referenced by controlledRotateY().

+

Referenced by controlledRotateY().

@@ -5148,16 +5173,16 @@

-

Definition at line 368 of file QuEST_common.c.

-
368  {
-
369 
-
370  Vector unitAxis = {0, 0, 1};
-
371  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
-
372 }
+

Definition at line 358 of file QuEST_common.c.

+
358  {
+
359 
+
360  Vector unitAxis = {0, 0, 1};
+
361  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
+
362 }
-

References statevec_controlledRotateAroundAxis().

+

References statevec_controlledRotateAroundAxis().

-

Referenced by controlledRotateZ().

+

Referenced by controlledRotateZ().

@@ -5205,16 +5230,16 @@

-

Definition at line 577 of file QuEST_common.c.

-
577  {
-
578 
-
579  long long int ctrlMask = 1LL << controlQubit;
-
580  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
581 }
+

Definition at line 567 of file QuEST_common.c.

+
567  {
+
568 
+
569  long long int ctrlMask = 1LL << controlQubit;
+
570  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
+
571 }
-

References statevec_multiControlledTwoQubitUnitary().

+

References statevec_multiControlledTwoQubitUnitary().

-

Referenced by controlledTwoQubitUnitary().

+

Referenced by controlledTwoQubitUnitary().

@@ -5256,47 +5281,47 @@

-

Definition at line 968 of file QuEST_cpu_distributed.c.

-
970 {
-
971  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
972  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
973  Complex rot1, rot2;
-
974 
-
975  // rank's chunk is in upper half of block
-
976  int rankIsUpper;
-
977  int pairRank; // rank of corresponding chunk
+

Definition at line 972 of file QuEST_cpu_distributed.c.

+
974 {
+
975  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
976  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
977  Complex rot1, rot2;
978 
-
979  if (useLocalDataOnly){
-
980  // all values required to update state vector lie in this rank
-
981  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
-
982  } else {
-
983  // need to get corresponding chunk of state vector from other rank
-
984  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
985  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
986  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
987  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
988  // get corresponding values from my pair
-
989  exchangeStateVectors(qureg, pairRank);
-
990 
-
991  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
-
992  // in the correct order
-
993  if (rankIsUpper){
-
994  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
995  qureg.stateVec, //upper
-
996  qureg.pairStateVec, //lower
-
997  qureg.stateVec); //output
-
998  } else {
-
999  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
-
1000  qureg.pairStateVec, //upper
-
1001  qureg.stateVec, //lower
-
1002  qureg.stateVec); //output
-
1003  }
-
1004  }
-
1005 }
+
979  // rank's chunk is in upper half of block
+
980  int rankIsUpper;
+
981  int pairRank; // rank of corresponding chunk
+
982 
+
983  if (useLocalDataOnly){
+
984  // all values required to update state vector lie in this rank
+
985  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
+
986  } else {
+
987  // need to get corresponding chunk of state vector from other rank
+
988  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
989  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
990  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
991  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
992  // get corresponding values from my pair
+
993  exchangeStateVectors(qureg, pairRank);
+
994 
+
995  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
+
996  // in the correct order
+
997  if (rankIsUpper){
+
998  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
999  qureg.stateVec, //upper
+
1000  qureg.pairStateVec, //lower
+
1001  qureg.stateVec); //output
+
1002  } else {
+
1003  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
+
1004  qureg.pairStateVec, //upper
+
1005  qureg.stateVec, //lower
+
1006  qureg.stateVec); //output
+
1007  }
+
1008  }
+
1009 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

-

Referenced by controlledUnitary().

+

Referenced by controlledUnitary().

@@ -5332,45 +5357,45 @@

-

Definition at line 1279 of file QuEST_cpu.c.

-
1280 {
-
1281  long long int numAmps = 1LL << numQubits;
-
1282  long long int numAmpsPerRank = numAmps/env.numRanks;
-
1283 
-
1284  if (numAmpsPerRank > SIZE_MAX) {
-
1285  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
-
1286  exit (EXIT_FAILURE);
-
1287  }
-
1288 
-
1289  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
-
1290  qureg->stateVec.real = malloc(arrSize);
-
1291  qureg->stateVec.imag = malloc(arrSize);
-
1292  if (env.numRanks>1){
-
1293  qureg->pairStateVec.real = malloc(arrSize);
-
1294  qureg->pairStateVec.imag = malloc(arrSize);
-
1295  }
-
1296 
-
1297  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
-
1298  && numAmpsPerRank ) {
-
1299  printf("Could not allocate memory!");
-
1300  exit (EXIT_FAILURE);
-
1301  }
-
1302 
-
1303  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
-
1304  && numAmpsPerRank ) {
-
1305  printf("Could not allocate memory!");
-
1306  exit (EXIT_FAILURE);
-
1307  }
-
1308 
-
1309  qureg->numQubitsInStateVec = numQubits;
-
1310  qureg->numAmpsTotal = numAmps;
-
1311  qureg->numAmpsPerChunk = numAmpsPerRank;
-
1312  qureg->chunkId = env.rank;
-
1313  qureg->numChunks = env.numRanks;
-
1314  qureg->isDensityMatrix = 0;
-
1315 }
+

Definition at line 1290 of file QuEST_cpu.c.

+
1291 {
+
1292  long long int numAmps = 1LL << numQubits;
+
1293  long long int numAmpsPerRank = numAmps/env.numRanks;
+
1294 
+
1295  if (numAmpsPerRank > SIZE_MAX) {
+
1296  printf("Could not allocate memory (cannot fit numAmps into size_t)!");
+
1297  exit (EXIT_FAILURE);
+
1298  }
+
1299 
+
1300  size_t arrSize = (size_t) (numAmpsPerRank * sizeof(*(qureg->stateVec.real)));
+
1301  qureg->stateVec.real = malloc(arrSize);
+
1302  qureg->stateVec.imag = malloc(arrSize);
+
1303  if (env.numRanks>1){
+
1304  qureg->pairStateVec.real = malloc(arrSize);
+
1305  qureg->pairStateVec.imag = malloc(arrSize);
+
1306  }
+
1307 
+
1308  if ( (!(qureg->stateVec.real) || !(qureg->stateVec.imag))
+
1309  && numAmpsPerRank ) {
+
1310  printf("Could not allocate memory!");
+
1311  exit (EXIT_FAILURE);
+
1312  }
+
1313 
+
1314  if ( env.numRanks>1 && (!(qureg->pairStateVec.real) || !(qureg->pairStateVec.imag))
+
1315  && numAmpsPerRank ) {
+
1316  printf("Could not allocate memory!");
+
1317  exit (EXIT_FAILURE);
+
1318  }
+
1319 
+
1320  qureg->numQubitsInStateVec = numQubits;
+
1321  qureg->numAmpsTotal = numAmps;
+
1322  qureg->numAmpsPerChunk = numAmpsPerRank;
+
1323  qureg->chunkId = env.rank;
+
1324  qureg->numChunks = env.numRanks;
+
1325  qureg->isDensityMatrix = 0;
+
1326 }
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, qreal, QuESTEnv::rank, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and Qureg::stateVec.

+

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numChunks, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, qreal, QuESTEnv::rank, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and Qureg::stateVec.

Referenced by createCloneQureg(), createDensityQureg(), and createQureg().

@@ -5402,26 +5427,26 @@

-

Definition at line 1317 of file QuEST_cpu.c.

-
1317  {
-
1318 
-
1319  qureg.numQubitsInStateVec = 0;
-
1320  qureg.numAmpsTotal = 0;
-
1321  qureg.numAmpsPerChunk = 0;
-
1322 
-
1323  free(qureg.stateVec.real);
-
1324  free(qureg.stateVec.imag);
-
1325  if (env.numRanks>1){
-
1326  free(qureg.pairStateVec.real);
-
1327  free(qureg.pairStateVec.imag);
-
1328  }
-
1329  qureg.stateVec.real = NULL;
-
1330  qureg.stateVec.imag = NULL;
-
1331  qureg.pairStateVec.real = NULL;
-
1332  qureg.pairStateVec.imag = NULL;
-
1333 }
+

Definition at line 1328 of file QuEST_cpu.c.

+
1328  {
+
1329 
+
1330  qureg.numQubitsInStateVec = 0;
+
1331  qureg.numAmpsTotal = 0;
+
1332  qureg.numAmpsPerChunk = 0;
+
1333 
+
1334  free(qureg.stateVec.real);
+
1335  free(qureg.stateVec.imag);
+
1336  if (env.numRanks>1){
+
1337  free(qureg.pairStateVec.real);
+
1338  free(qureg.pairStateVec.imag);
+
1339  }
+
1340  qureg.stateVec.real = NULL;
+
1341  qureg.stateVec.imag = NULL;
+
1342  qureg.pairStateVec.real = NULL;
+
1343  qureg.pairStateVec.imag = NULL;
+
1344 }
-

References Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, Qureg::secondLevelReduction, and Qureg::stateVec.

+

References Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, QuESTEnv::numRanks, Qureg::pairStateVec, Qureg::secondLevelReduction, and Qureg::stateVec.

Referenced by destroyQureg().

@@ -5453,20 +5478,20 @@

-

Definition at line 218 of file QuEST_cpu_distributed.c.

-
218  {
-
219  int chunkId = getChunkIdFromIndex(qureg, index);
-
220  qreal el;
-
221  if (qureg.chunkId==chunkId){
-
222  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
-
223  }
-
224  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
225  return el;
-
226 }
+

Definition at line 222 of file QuEST_cpu_distributed.c.

+
222  {
+
223  int chunkId = getChunkIdFromIndex(qureg, index);
+
224  qreal el;
+
225  if (qureg.chunkId==chunkId){
+
226  el = qureg.stateVec.imag[index-chunkId*qureg.numAmpsPerChunk];
+
227  }
+
228  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
+
229  return el;
+
230 }
-

References Qureg::chunkId, Qureg::deviceStateVec, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, Qureg::deviceStateVec, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

+

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

@@ -5496,16 +5521,16 @@

-

Definition at line 258 of file QuEST_common.c.

-
258  {
-
259  qreal real = statevec_getRealAmp(qureg, index);
-
260  qreal imag = statevec_getImagAmp(qureg, index);
-
261  return real*real + imag*imag;
-
262 }
+

Definition at line 248 of file QuEST_common.c.

+
248  {
+
249  qreal real = statevec_getRealAmp(qureg, index);
+
250  qreal imag = statevec_getImagAmp(qureg, index);
+
251  return real*real + imag*imag;
+
252 }
-

References qreal, statevec_getImagAmp(), and statevec_getRealAmp().

+

References qreal, statevec_getImagAmp(), and statevec_getRealAmp().

-

Referenced by getProbAmp().

+

Referenced by getProbAmp().

@@ -5535,20 +5560,20 @@

-

Definition at line 208 of file QuEST_cpu_distributed.c.

-
208  {
-
209  int chunkId = getChunkIdFromIndex(qureg, index);
-
210  qreal el;
-
211  if (qureg.chunkId==chunkId){
-
212  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
-
213  }
-
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
-
215  return el;
-
216 }
+

Definition at line 212 of file QuEST_cpu_distributed.c.

+
212  {
+
213  int chunkId = getChunkIdFromIndex(qureg, index);
+
214  qreal el;
+
215  if (qureg.chunkId==chunkId){
+
216  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
+
217  }
+
218  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
+
219  return el;
+
220 }
-

References Qureg::chunkId, Qureg::deviceStateVec, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, Qureg::deviceStateVec, getChunkIdFromIndex(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

+

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

@@ -5578,44 +5603,44 @@

-

Definition at line 1254 of file QuEST_cpu_distributed.c.

-
1255 {
-
1256  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1257  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1258 
-
1259  // rank's chunk is in upper half of block
-
1260  int rankIsUpper;
-
1261  int pairRank; // rank of corresponding chunk
+

Definition at line 1258 of file QuEST_cpu_distributed.c.

+
1259 {
+
1260  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1261  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1262 
-
1263  if (useLocalDataOnly){
-
1264  // all values required to update state vector lie in this rank
-
1265  statevec_hadamardLocal(qureg, targetQubit);
-
1266  } else {
-
1267  // need to get corresponding chunk of state vector from other rank
-
1268  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1269  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1270  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1271  // get corresponding values from my pair
-
1272  exchangeStateVectors(qureg, pairRank);
-
1273  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
-
1274  // in the correct order
-
1275  if (rankIsUpper){
- -
1277  qureg.stateVec, //upper
-
1278  qureg.pairStateVec, //lower
-
1279  qureg.stateVec, rankIsUpper); //output
-
1280  } else {
- -
1282  qureg.pairStateVec, //upper
-
1283  qureg.stateVec, //lower
-
1284  qureg.stateVec, rankIsUpper); //output
-
1285  }
-
1286  }
-
1287 }
+
1263  // rank's chunk is in upper half of block
+
1264  int rankIsUpper;
+
1265  int pairRank; // rank of corresponding chunk
+
1266 
+
1267  if (useLocalDataOnly){
+
1268  // all values required to update state vector lie in this rank
+
1269  statevec_hadamardLocal(qureg, targetQubit);
+
1270  } else {
+
1271  // need to get corresponding chunk of state vector from other rank
+
1272  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1273  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1274  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
1275  // get corresponding values from my pair
+
1276  exchangeStateVectors(qureg, pairRank);
+
1277  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
+
1278  // in the correct order
+
1279  if (rankIsUpper){
+ +
1281  qureg.stateVec, //upper
+
1282  qureg.pairStateVec, //lower
+
1283  qureg.stateVec, rankIsUpper); //output
+
1284  } else {
+ +
1286  qureg.pairStateVec, //upper
+
1287  qureg.stateVec, //lower
+
1288  qureg.stateVec, rankIsUpper); //output
+
1289  }
+
1290  }
+
1291 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

-

Referenced by agnostic_applyQFT(), and hadamard().

+

Referenced by agnostic_applyQFT(), and hadamard().

@@ -5635,39 +5660,39 @@

-

Definition at line 1453 of file QuEST_cpu.c.

-
1454 {
-
1455  long long int stateVecSize;
-
1456  long long int index;
-
1457 
-
1458  // dimension of the state vector
-
1459  stateVecSize = qureg.numAmpsPerChunk;
-
1460 
-
1461  // Can't use qureg->stateVec as a private OMP var
-
1462  qreal *stateVecReal = qureg.stateVec.real;
-
1463  qreal *stateVecImag = qureg.stateVec.imag;
-
1464 
-
1465  // initialise the state-vector to all-zeroes
-
1466 # ifdef _OPENMP
-
1467 # pragma omp parallel \
-
1468  default (none) \
-
1469  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1470  private (index)
-
1471 # endif
-
1472  {
-
1473 # ifdef _OPENMP
-
1474 # pragma omp for schedule (static)
-
1475 # endif
-
1476  for (index=0; index<stateVecSize; index++) {
-
1477  stateVecReal[index] = 0.0;
-
1478  stateVecImag[index] = 0.0;
-
1479  }
-
1480  }
-
1481 }
+

Definition at line 1464 of file QuEST_cpu.c.

+
1465 {
+
1466  long long int stateVecSize;
+
1467  long long int index;
+
1468 
+
1469  // dimension of the state vector
+
1470  stateVecSize = qureg.numAmpsPerChunk;
+
1471 
+
1472  // Can't use qureg->stateVec as a private OMP var
+
1473  qreal *stateVecReal = qureg.stateVec.real;
+
1474  qreal *stateVecImag = qureg.stateVec.imag;
+
1475 
+
1476  // initialise the state-vector to all-zeroes
+
1477 # ifdef _OPENMP
+
1478 # pragma omp parallel \
+
1479  default (none) \
+
1480  shared (stateVecSize, stateVecReal, stateVecImag) \
+
1481  private (index)
+
1482 # endif
+
1483  {
+
1484 # ifdef _OPENMP
+
1485 # pragma omp for schedule (static)
+
1486 # endif
+
1487  for (index=0; index<stateVecSize; index++) {
+
1488  stateVecReal[index] = 0.0;
+
1489  stateVecImag[index] = 0.0;
+
1490  }
+
1491  }
+
1492 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by initBlankState(), statevec_applyPauliSum(), and statevec_initZeroState().

+

Referenced by initBlankState(), statevec_applyPauliSum(), and statevec_initZeroState().

@@ -5697,41 +5722,41 @@

-

Definition at line 1525 of file QuEST_cpu.c.

-
1526 {
-
1527  long long int stateVecSize;
-
1528  long long int index;
-
1529 
-
1530  // dimension of the state vector
-
1531  stateVecSize = qureg.numAmpsPerChunk;
-
1532 
-
1533  // Can't use qureg->stateVec as a private OMP var
-
1534  qreal *stateVecReal = qureg.stateVec.real;
-
1535  qreal *stateVecImag = qureg.stateVec.imag;
-
1536 
-
1537  // initialise the state to vector to all zeros
-
1538 # ifdef _OPENMP
-
1539 # pragma omp parallel \
-
1540  default (none) \
-
1541  shared (stateVecSize, stateVecReal, stateVecImag) \
-
1542  private (index)
-
1543 # endif
-
1544  {
-
1545 # ifdef _OPENMP
-
1546 # pragma omp for schedule (static)
-
1547 # endif
-
1548  for (index=0; index<stateVecSize; index++) {
-
1549  stateVecReal[index] = 0.0;
-
1550  stateVecImag[index] = 0.0;
-
1551  }
-
1552  }
-
1553 
-
1554  // give the specified classical state prob 1
-
1555  if (qureg.chunkId == stateInd/stateVecSize){
-
1556  stateVecReal[stateInd % stateVecSize] = 1.0;
-
1557  stateVecImag[stateInd % stateVecSize] = 0.0;
-
1558  }
-
1559 }
+

Definition at line 1536 of file QuEST_cpu.c.

+
1537 {
+
1538  long long int stateVecSize;
+
1539  long long int index;
+
1540 
+
1541  // dimension of the state vector
+
1542  stateVecSize = qureg.numAmpsPerChunk;
+
1543 
+
1544  // Can't use qureg->stateVec as a private OMP var
+
1545  qreal *stateVecReal = qureg.stateVec.real;
+
1546  qreal *stateVecImag = qureg.stateVec.imag;
+
1547 
+
1548  // initialise the state to vector to all zeros
+
1549 # ifdef _OPENMP
+
1550 # pragma omp parallel \
+
1551  default (none) \
+
1552  shared (stateVecSize, stateVecReal, stateVecImag) \
+
1553  private (index)
+
1554 # endif
+
1555  {
+
1556 # ifdef _OPENMP
+
1557 # pragma omp for schedule (static)
+
1558 # endif
+
1559  for (index=0; index<stateVecSize; index++) {
+
1560  stateVecReal[index] = 0.0;
+
1561  stateVecImag[index] = 0.0;
+
1562  }
+
1563  }
+
1564 
+
1565  // give the specified classical state prob 1
+
1566  if (qureg.chunkId == stateInd/stateVecSize){
+
1567  stateVecReal[stateInd % stateVecSize] = 1.0;
+
1568  stateVecImag[stateInd % stateVecSize] = 0.0;
+
1569  }
+
1570 }

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

@@ -5763,42 +5788,42 @@

Definition at line 1646 of file QuEST_cpu.c.

-
1647 {
-
1648  long long int chunkSize;
-
1649  long long int index;
-
1650  long long int indexOffset;
-
1651 
-
1652  // dimension of the state vector
-
1653  chunkSize = qureg.numAmpsPerChunk;
-
1654 
-
1655  // Can't use qureg->stateVec as a private OMP var
-
1656  qreal *stateVecReal = qureg.stateVec.real;
-
1657  qreal *stateVecImag = qureg.stateVec.imag;
-
1658 
-
1659  indexOffset = chunkSize * qureg.chunkId;
-
1660 
-
1661  // initialise the state to |0000..0000>
-
1662 # ifdef _OPENMP
-
1663 # pragma omp parallel \
-
1664  default (none) \
-
1665  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
-
1666  private (index)
-
1667 # endif
-
1668  {
-
1669 # ifdef _OPENMP
-
1670 # pragma omp for schedule (static)
-
1671 # endif
-
1672  for (index=0; index<chunkSize; index++) {
-
1673  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
-
1674  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
-
1675  }
-
1676  }
-
1677 }
+

Definition at line 1657 of file QuEST_cpu.c.

+
1658 {
+
1659  long long int chunkSize;
+
1660  long long int index;
+
1661  long long int indexOffset;
+
1662 
+
1663  // dimension of the state vector
+
1664  chunkSize = qureg.numAmpsPerChunk;
+
1665 
+
1666  // Can't use qureg->stateVec as a private OMP var
+
1667  qreal *stateVecReal = qureg.stateVec.real;
+
1668  qreal *stateVecImag = qureg.stateVec.imag;
+
1669 
+
1670  indexOffset = chunkSize * qureg.chunkId;
+
1671 
+
1672  // initialise the state to |0000..0000>
+
1673 # ifdef _OPENMP
+
1674 # pragma omp parallel \
+
1675  default (none) \
+
1676  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
+
1677  private (index)
+
1678 # endif
+
1679  {
+
1680 # ifdef _OPENMP
+
1681 # pragma omp for schedule (static)
+
1682 # endif
+
1683  for (index=0; index<chunkSize; index++) {
+
1684  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
+
1685  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
+
1686  }
+
1687  }
+
1688 }

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by initDebugState().

+

Referenced by initDebugState().

@@ -5818,37 +5843,37 @@

-

Definition at line 1493 of file QuEST_cpu.c.

-
1494 {
-
1495  long long int chunkSize, stateVecSize;
-
1496  long long int index;
-
1497 
-
1498  // dimension of the state vector
-
1499  chunkSize = qureg.numAmpsPerChunk;
-
1500  stateVecSize = chunkSize*qureg.numChunks;
-
1501  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
-
1502 
-
1503  // Can't use qureg->stateVec as a private OMP var
-
1504  qreal *stateVecReal = qureg.stateVec.real;
-
1505  qreal *stateVecImag = qureg.stateVec.imag;
-
1506 
-
1507  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
-
1508 # ifdef _OPENMP
-
1509 # pragma omp parallel \
-
1510  default (none) \
-
1511  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
-
1512  private (index)
-
1513 # endif
-
1514  {
-
1515 # ifdef _OPENMP
-
1516 # pragma omp for schedule (static)
-
1517 # endif
-
1518  for (index=0; index<chunkSize; index++) {
-
1519  stateVecReal[index] = normFactor;
-
1520  stateVecImag[index] = 0.0;
-
1521  }
-
1522  }
-
1523 }
+

Definition at line 1504 of file QuEST_cpu.c.

+
1505 {
+
1506  long long int chunkSize, stateVecSize;
+
1507  long long int index;
+
1508 
+
1509  // dimension of the state vector
+
1510  chunkSize = qureg.numAmpsPerChunk;
+
1511  stateVecSize = chunkSize*qureg.numChunks;
+
1512  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
+
1513 
+
1514  // Can't use qureg->stateVec as a private OMP var
+
1515  qreal *stateVecReal = qureg.stateVec.real;
+
1516  qreal *stateVecImag = qureg.stateVec.imag;
+
1517 
+
1518  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
+
1519 # ifdef _OPENMP
+
1520 # pragma omp parallel \
+
1521  default (none) \
+
1522  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
+
1523  private (index)
+
1524 # endif
+
1525  {
+
1526 # ifdef _OPENMP
+
1527 # pragma omp for schedule (static)
+
1528 # endif
+
1529  for (index=0; index<chunkSize; index++) {
+
1530  stateVecReal[index] = normFactor;
+
1531  stateVecImag[index] = 0.0;
+
1532  }
+
1533  }
+
1534 }

References Qureg::deviceStateVec, Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

@@ -5888,60 +5913,60 @@

-

Definition at line 1680 of file QuEST_cpu.c.

-
1680  {
-
1681  long long int chunkSize, stateVecSize;
-
1682  long long int indexInChunk, totalIndex;
-
1683 
-
1684  chunkSize = qureg->numAmpsPerChunk;
-
1685  stateVecSize = chunkSize*qureg->numChunks;
-
1686 
-
1687  qreal *stateVecReal = qureg->stateVec.real;
-
1688  qreal *stateVecImag = qureg->stateVec.imag;
-
1689 
-
1690  FILE *fp;
-
1691  char line[200];
-
1692 
-
1693  for (int rank=0; rank<(qureg->numChunks); rank++){
-
1694  if (rank==qureg->chunkId){
-
1695  fp = fopen(filename, "r");
-
1696 
-
1697  // indicate file open failure
-
1698  if (fp == NULL)
-
1699  return 0;
-
1700 
-
1701  indexInChunk = 0; totalIndex = 0;
-
1702  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
-
1703  if (line[0]!='#'){
-
1704  int chunkId = (int) (totalIndex/chunkSize);
-
1705  if (chunkId==qureg->chunkId){
-
1706  # if QuEST_PREC==1
-
1707  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
-
1708  &(stateVecImag[indexInChunk]));
-
1709  # elif QuEST_PREC==2
-
1710  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
-
1711  &(stateVecImag[indexInChunk]));
-
1712  # elif QuEST_PREC==4
-
1713  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
-
1714  &(stateVecImag[indexInChunk]));
-
1715  # endif
-
1716  indexInChunk += 1;
-
1717  }
-
1718  totalIndex += 1;
-
1719  }
-
1720  }
-
1721  fclose(fp);
-
1722  }
-
1723  syncQuESTEnv(env);
-
1724  }
-
1725 
-
1726  // indicate success
-
1727  return 1;
-
1728 }
+

Definition at line 1691 of file QuEST_cpu.c.

+
1691  {
+
1692  long long int chunkSize, stateVecSize;
+
1693  long long int indexInChunk, totalIndex;
+
1694 
+
1695  chunkSize = qureg->numAmpsPerChunk;
+
1696  stateVecSize = chunkSize*qureg->numChunks;
+
1697 
+
1698  qreal *stateVecReal = qureg->stateVec.real;
+
1699  qreal *stateVecImag = qureg->stateVec.imag;
+
1700 
+
1701  FILE *fp;
+
1702  char line[200];
+
1703 
+
1704  for (int rank=0; rank<(qureg->numChunks); rank++){
+
1705  if (rank==qureg->chunkId){
+
1706  fp = fopen(filename, "r");
+
1707 
+
1708  // indicate file open failure
+
1709  if (fp == NULL)
+
1710  return 0;
+
1711 
+
1712  indexInChunk = 0; totalIndex = 0;
+
1713  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
+
1714  if (line[0]!='#'){
+
1715  int chunkId = (int) (totalIndex/chunkSize);
+
1716  if (chunkId==qureg->chunkId){
+
1717  # if QuEST_PREC==1
+
1718  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
+
1719  &(stateVecImag[indexInChunk]));
+
1720  # elif QuEST_PREC==2
+
1721  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
+
1722  &(stateVecImag[indexInChunk]));
+
1723  # elif QuEST_PREC==4
+
1724  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
+
1725  &(stateVecImag[indexInChunk]));
+
1726  # endif
+
1727  indexInChunk += 1;
+
1728  }
+
1729  totalIndex += 1;
+
1730  }
+
1731  }
+
1732  fclose(fp);
+
1733  }
+
1734  syncQuESTEnv(env);
+
1735  }
+
1736 
+
1737  // indicate success
+
1738  return 1;
+
1739 }
-

References Qureg::chunkId, copyStateToGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Qureg::stateVec, and syncQuESTEnv().

+

References Qureg::chunkId, copyStateToGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, Qureg::stateVec, and syncQuESTEnv().

-

Referenced by initStateFromSingleFile().

+

Referenced by initStateFromSingleFile().

@@ -5987,49 +6012,49 @@

Definition at line 1600 of file QuEST_cpu.c.

-
1601 {
-
1602  long long int chunkSize, stateVecSize;
-
1603  long long int index;
-
1604  int bit;
-
1605  long long int chunkId=qureg->chunkId;
-
1606 
-
1607  // dimension of the state vector
-
1608  chunkSize = qureg->numAmpsPerChunk;
-
1609  stateVecSize = chunkSize*qureg->numChunks;
-
1610  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
-
1611 
-
1612  // Can't use qureg->stateVec as a private OMP var
-
1613  qreal *stateVecReal = qureg->stateVec.real;
-
1614  qreal *stateVecImag = qureg->stateVec.imag;
-
1615 
-
1616  // initialise the state to |0000..0000>
-
1617 # ifdef _OPENMP
-
1618 # pragma omp parallel \
-
1619  default (none) \
-
1620  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
-
1621  private (index, bit)
-
1622 # endif
-
1623  {
-
1624 # ifdef _OPENMP
-
1625 # pragma omp for schedule (static)
-
1626 # endif
-
1627  for (index=0; index<chunkSize; index++) {
-
1628  bit = extractBit(qubitId, index+chunkId*chunkSize);
-
1629  if (bit==outcome) {
-
1630  stateVecReal[index] = normFactor;
-
1631  stateVecImag[index] = 0.0;
-
1632  } else {
-
1633  stateVecReal[index] = 0.0;
-
1634  stateVecImag[index] = 0.0;
-
1635  }
-
1636  }
-
1637  }
-
1638 }
+

Definition at line 1611 of file QuEST_cpu.c.

+
1612 {
+
1613  long long int chunkSize, stateVecSize;
+
1614  long long int index;
+
1615  int bit;
+
1616  long long int chunkId=qureg->chunkId;
+
1617 
+
1618  // dimension of the state vector
+
1619  chunkSize = qureg->numAmpsPerChunk;
+
1620  stateVecSize = chunkSize*qureg->numChunks;
+
1621  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
+
1622 
+
1623  // Can't use qureg->stateVec as a private OMP var
+
1624  qreal *stateVecReal = qureg->stateVec.real;
+
1625  qreal *stateVecImag = qureg->stateVec.imag;
+
1626 
+
1627  // initialise the state to |0000..0000>
+
1628 # ifdef _OPENMP
+
1629 # pragma omp parallel \
+
1630  default (none) \
+
1631  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome, chunkId) \
+
1632  private (index, bit)
+
1633 # endif
+
1634  {
+
1635 # ifdef _OPENMP
+
1636 # pragma omp for schedule (static)
+
1637 # endif
+
1638  for (index=0; index<chunkSize; index++) {
+
1639  bit = extractBit(qubitId, index+chunkId*chunkSize);
+
1640  if (bit==outcome) {
+
1641  stateVecReal[index] = normFactor;
+
1642  stateVecImag[index] = 0.0;
+
1643  } else {
+
1644  stateVecReal[index] = 0.0;
+
1645  stateVecImag[index] = 0.0;
+
1646  }
+
1647  }
+
1648  }
+
1649 }

References Qureg::chunkId, Qureg::deviceStateVec, extractBit(), Qureg::numAmpsPerChunk, Qureg::numChunks, qreal, and Qureg::stateVec.

-

Referenced by initStateOfSingleQubit().

+

Referenced by initStateOfSingleQubit().

@@ -6049,17 +6074,17 @@

-

Definition at line 1483 of file QuEST_cpu.c.

-
1484 {
-
1485  statevec_initBlankState(qureg);
-
1486  if (qureg.chunkId==0){
-
1487  // zero state |0000..0000> has probability 1
-
1488  qureg.stateVec.real[0] = 1.0;
-
1489  qureg.stateVec.imag[0] = 0.0;
-
1490  }
-
1491 }
+

Definition at line 1494 of file QuEST_cpu.c.

+
1495 {
+
1496  statevec_initBlankState(qureg);
+
1497  if (qureg.chunkId==0){
+
1498  // zero state |0000..0000> has probability 1
+
1499  qureg.stateVec.real[0] = 1.0;
+
1500  qureg.stateVec.imag[0] = 0.0;
+
1501  }
+
1502 }
-

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, and statevec_initBlankState().

+

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, Qureg::stateVec, and statevec_initBlankState().

Referenced by initZeroState().

@@ -6097,18 +6122,18 @@

-

Definition at line 374 of file QuEST_common.c.

-
374  {
-
375 
-
376  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
-
377  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
-
378  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
-
379  return outcome;
-
380 }
+

Definition at line 364 of file QuEST_common.c.

+
364  {
+
365 
+
366  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
+
367  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
+
368  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
+
369  return outcome;
+
370 }
-

References generateMeasurementOutcome(), qreal, statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

+

References generateMeasurementOutcome(), qreal, statevec_calcProbOfOutcome(), and statevec_collapseToKnownProbOutcome().

-

Referenced by measure(), and measureWithStats().

+

Referenced by measure(), and measureWithStats().

@@ -6144,54 +6169,54 @@

-

Definition at line 1093 of file QuEST_cpu_distributed.c.

-
1094 {
-
1095  /* operation is the same regardless of control and target ordering, hence
-
1096  * we accept only bitMasks (for convenience of caller, when shifting qubits
-
1097  * for density matrices)
-
1098  */
-
1099 
-
1100  // global index of the first basis state in this node
-
1101  long long int firstInd = qureg.chunkId * qureg.numAmpsPerChunk;
-
1102 
-
1103  /* optimisation: if this node doesn't contain any amplitudes for which {ctrls}={1}
-
1104  * (and hence, neither does the pair node), then these pair nodes have nothing to modify
-
1105  * nor any need to communicate, and can halt. No ctrls are contained in the node
-
1106  * if the distance from the first index, to the next index where {ctrls}=1, is
-
1107  * greater than the total contained amplitudes. This is a worthwhile optimisation,
-
1108  * since although we must still wait for the slowest node, we have potentially reduced
-
1109  * the network traffic and might avoid saturation.
-
1110  */
-
1111  if ((firstInd|ctrlMask) - firstInd >= qureg.numAmpsPerChunk)
-
1112  return;
-
1113 
-
1114  /* nodes communicate pairwise, and (ignoring ctrls) swap all their amplitudes with mate.
-
1115  * hence we find |pairState> = X_{targs}|firstStateInNode>, determine which node contains
-
1116  * |pairState>, and swap state-vector with it (unless it happens to be this node).
-
1117  */
-
1118 
-
1119  // global index of the corresponding NOT'd first basis state
-
1120  long long int pairInd = firstInd ^ targMask;
-
1121  int pairRank = pairInd / qureg.numAmpsPerChunk;
-
1122  int useLocalDataOnly = (pairRank == qureg.chunkId);
-
1123 
-
1124  if (useLocalDataOnly) {
-
1125  // swaps amplitudes locally, setting |a>=X|b>, and |b>=X|a>
-
1126  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
-
1127  } else {
-
1128  // swaps amplitudes with pair node
-
1129  exchangeStateVectors(qureg, pairRank);
-
1130  // modifies only |a>=X|b> (pair node handles the converse)
- -
1132  qureg, ctrlMask, targMask,
-
1133  qureg.pairStateVec, // in
-
1134  qureg.stateVec); // out
-
1135  }
-
1136 }
+

Definition at line 1097 of file QuEST_cpu_distributed.c.

+
1098 {
+
1099  /* operation is the same regardless of control and target ordering, hence
+
1100  * we accept only bitMasks (for convenience of caller, when shifting qubits
+
1101  * for density matrices)
+
1102  */
+
1103 
+
1104  // global index of the first basis state in this node
+
1105  long long int firstInd = qureg.chunkId * qureg.numAmpsPerChunk;
+
1106 
+
1107  /* optimisation: if this node doesn't contain any amplitudes for which {ctrls}={1}
+
1108  * (and hence, neither does the pair node), then these pair nodes have nothing to modify
+
1109  * nor any need to communicate, and can halt. No ctrls are contained in the node
+
1110  * if the distance from the first index, to the next index where {ctrls}=1, is
+
1111  * greater than the total contained amplitudes. This is a worthwhile optimisation,
+
1112  * since although we must still wait for the slowest node, we have potentially reduced
+
1113  * the network traffic and might avoid saturation.
+
1114  */
+
1115  if ((firstInd|ctrlMask) - firstInd >= qureg.numAmpsPerChunk)
+
1116  return;
+
1117 
+
1118  /* nodes communicate pairwise, and (ignoring ctrls) swap all their amplitudes with mate.
+
1119  * hence we find |pairState> = X_{targs}|firstStateInNode>, determine which node contains
+
1120  * |pairState>, and swap state-vector with it (unless it happens to be this node).
+
1121  */
+
1122 
+
1123  // global index of the corresponding NOT'd first basis state
+
1124  long long int pairInd = firstInd ^ targMask;
+
1125  int pairRank = pairInd / qureg.numAmpsPerChunk;
+
1126  int useLocalDataOnly = (pairRank == qureg.chunkId);
+
1127 
+
1128  if (useLocalDataOnly) {
+
1129  // swaps amplitudes locally, setting |a>=X|b>, and |b>=X|a>
+
1130  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
+
1131  } else {
+
1132  // swaps amplitudes with pair node
+
1133  exchangeStateVectors(qureg, pairRank);
+
1134  // modifies only |a>=X|b> (pair node handles the converse)
+ +
1136  qureg, ctrlMask, targMask,
+
1137  qureg.pairStateVec, // in
+
1138  qureg.stateVec); // out
+
1139  }
+
1140 }
-

References Qureg::chunkId, exchangeStateVectors(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_multiControlledMultiQubitNotDistributed(), and statevec_multiControlledMultiQubitNotLocal().

+

References Qureg::chunkId, exchangeStateVectors(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_multiControlledMultiQubitNotDistributed(), and statevec_multiControlledMultiQubitNotLocal().

-

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

+

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

@@ -6243,54 +6268,54 @@

Todo:
refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.
-

Definition at line 1503 of file QuEST_cpu_distributed.c.

-
1503  {
-
1504 
-
1505  // bit mask of target qubits (for quick collision checking)
-
1506  long long int targMask = getQubitBitMask(targs, numTargs);
-
1507 
-
1508  // find lowest qubit available for swapping (isn't in targs)
-
1509  int freeQb=0;
-
1510  while (maskContainsBit(targMask, freeQb))
-
1511  freeQb++;
-
1512 
-
1513  // assign indices of where each target will be swapped to (else itself)
-
1514  int swapTargs[numTargs];
-
1515  for (int t=0; t<numTargs; t++) {
-
1516  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
-
1517  swapTargs[t] = targs[t];
-
1518  else {
-
1519  // mark swap
-
1520  swapTargs[t] = freeQb;
-
1521 
-
1522  // update ctrlMask if swapped-out qubit was a control
-
1523  if (maskContainsBit(ctrlMask, swapTargs[t]))
-
1524  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
-
1525 
-
1526  // locate next available on-chunk qubit
-
1527  freeQb++;
-
1528  while (maskContainsBit(targMask, freeQb))
-
1529  freeQb++;
-
1530  }
-
1531  }
-
1532 
-
1533  // perform swaps as necessary
-
1534  for (int t=0; t<numTargs; t++)
-
1535  if (swapTargs[t] != targs[t])
-
1536  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1537 
-
1538  // all target qubits have now been swapped into local memory
-
1539  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
-
1540 
-
1541  // undo swaps
-
1542  for (int t=0; t<numTargs; t++)
-
1543  if (swapTargs[t] != targs[t])
-
1544  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
-
1545 }
+

Definition at line 1514 of file QuEST_cpu_distributed.c.

+
1514  {
+
1515 
+
1516  // bit mask of target qubits (for quick collision checking)
+
1517  long long int targMask = getQubitBitMask(targs, numTargs);
+
1518 
+
1519  // find lowest qubit available for swapping (isn't in targs)
+
1520  int freeQb=0;
+
1521  while (maskContainsBit(targMask, freeQb))
+
1522  freeQb++;
+
1523 
+
1524  // assign indices of where each target will be swapped to (else itself)
+
1525  int swapTargs[numTargs];
+
1526  for (int t=0; t<numTargs; t++) {
+
1527  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
+
1528  swapTargs[t] = targs[t];
+
1529  else {
+
1530  // mark swap
+
1531  swapTargs[t] = freeQb;
+
1532 
+
1533  // update ctrlMask if swapped-out qubit was a control
+
1534  if (maskContainsBit(ctrlMask, swapTargs[t]))
+
1535  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
+
1536 
+
1537  // locate next available on-chunk qubit
+
1538  freeQb++;
+
1539  while (maskContainsBit(targMask, freeQb))
+
1540  freeQb++;
+
1541  }
+
1542  }
+
1543 
+
1544  // perform swaps as necessary
+
1545  for (int t=0; t<numTargs; t++)
+
1546  if (swapTargs[t] != targs[t])
+
1547  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
+
1548 
+
1549  // all target qubits have now been swapped into local memory
+
1550  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
+
1551 
+
1552  // undo swaps
+
1553  for (int t=0; t<numTargs; t++)
+
1554  if (swapTargs[t] != targs[t])
+
1555  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
+
1556 }
-

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), ComplexMatrixN::imag, maskContainsBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, ComplexMatrixN::real, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

+

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), ComplexMatrixN::imag, maskContainsBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, ComplexMatrixN::real, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

-

Referenced by applyMultiControlledMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

+

Referenced by applyMultiControlledMatrixN(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

@@ -6350,48 +6375,48 @@

-

Definition at line 463 of file QuEST_common.c.

-
466  {
-
467  qreal fac = 1/sqrt(2);
-
468  qreal sgn = (applyConj)? 1 : -1;
-
469  ComplexMatrix2 uRx = {.real={{fac,0},{0,fac}}, .imag={{0,sgn*fac},{sgn*fac,0}}}; // Rx(pi/2)* rotates Z -> Y
-
470  ComplexMatrix2 uRy = {.real={{fac,fac},{-fac,fac}}, .imag={{0,0},{0,0}}}; // Ry(-pi/2) rotates Z -> X
-
471 
-
472  // this function is controlled on the all-one state, so no ctrl flips
-
473  long long int ctrlFlipMask = 0;
-
474 
-
475  // mask may be modified to remove superfluous Identity ops
-
476  long long int targMask = getQubitBitMask(targetQubits, numTargets);
-
477 
-
478  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
479  for (int t=0; t < numTargets; t++) {
-
480  if (targetPaulis[t] == PAULI_I)
-
481  targMask -= 1LL << targetQubits[t]; // remove target from mask
-
482  if (targetPaulis[t] == PAULI_X)
-
483  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
-
484  if (targetPaulis[t] == PAULI_Y)
-
485  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
-
486  // (targetPaulis[t] == 3) is Z basis
-
487  }
-
488 
-
489  // does nothing if there are no qubits to 'rotate'
-
490  if (targMask != 0)
-
491  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, (applyConj)? -angle : angle);
-
492 
-
493  // undo X and Y basis rotations
-
494  uRx.imag[0][1] *= -1; uRx.imag[1][0] *= -1;
-
495  uRy.real[0][1] *= -1; uRy.real[1][0] *= -1;
-
496  for (int t=0; t < numTargets; t++) {
-
497  if (targetPaulis[t] == PAULI_X)
-
498  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
-
499  if (targetPaulis[t] == PAULI_Y)
-
500  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
-
501  }
-
502 }
+

Definition at line 453 of file QuEST_common.c.

+
456  {
+
457  qreal fac = 1/sqrt(2);
+
458  qreal sgn = (applyConj)? 1 : -1;
+
459  ComplexMatrix2 uRx = {.real={{fac,0},{0,fac}}, .imag={{0,sgn*fac},{sgn*fac,0}}}; // Rx(pi/2)* rotates Z -> Y
+
460  ComplexMatrix2 uRy = {.real={{fac,fac},{-fac,fac}}, .imag={{0,0},{0,0}}}; // Ry(-pi/2) rotates Z -> X
+
461 
+
462  // this function is controlled on the all-one state, so no ctrl flips
+
463  long long int ctrlFlipMask = 0;
+
464 
+
465  // mask may be modified to remove superfluous Identity ops
+
466  long long int targMask = getQubitBitMask(targetQubits, numTargets);
+
467 
+
468  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
+
469  for (int t=0; t < numTargets; t++) {
+
470  if (targetPaulis[t] == PAULI_I)
+
471  targMask -= 1LL << targetQubits[t]; // remove target from mask
+
472  if (targetPaulis[t] == PAULI_X)
+
473  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
+
474  if (targetPaulis[t] == PAULI_Y)
+
475  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
+
476  // (targetPaulis[t] == 3) is Z basis
+
477  }
+
478 
+
479  // does nothing if there are no qubits to 'rotate'
+
480  if (targMask != 0)
+
481  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, (applyConj)? -angle : angle);
+
482 
+
483  // undo X and Y basis rotations
+
484  uRx.imag[0][1] *= -1; uRx.imag[1][0] *= -1;
+
485  uRy.real[0][1] *= -1; uRy.real[1][0] *= -1;
+
486  for (int t=0; t < numTargets; t++) {
+
487  if (targetPaulis[t] == PAULI_X)
+
488  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRy);
+
489  if (targetPaulis[t] == PAULI_Y)
+
490  statevec_multiControlledUnitary(qureg, ctrlMask, ctrlFlipMask, targetQubits[t], uRx);
+
491  }
+
492 }
-

References getQubitBitMask(), ComplexMatrix2::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, ComplexMatrix2::real, statevec_multiControlledMultiRotateZ(), and statevec_multiControlledUnitary().

+

References getQubitBitMask(), ComplexMatrix2::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, ComplexMatrix2::real, statevec_multiControlledMultiRotateZ(), and statevec_multiControlledUnitary().

-

Referenced by multiControlledMultiRotatePauli().

+

Referenced by multiControlledMultiRotatePauli().

@@ -6433,53 +6458,53 @@

-

Definition at line 3319 of file QuEST_cpu.c.

-
3320 {
-
3321  long long int offset = qureg.chunkId * qureg.numAmpsPerChunk;
-
3322 
-
3323  long long int stateVecSize = qureg.numAmpsPerChunk;
-
3324  qreal *stateVecReal = qureg.stateVec.real;
-
3325  qreal *stateVecImag = qureg.stateVec.imag;
-
3326 
-
3327  qreal stateReal, stateImag;
-
3328  qreal cosAngle = cos(angle/2.0);
-
3329  qreal sinAngle = sin(angle/2.0);
-
3330 
-
3331  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3332  // exp(-angle/2 i fac_j)|j>
-
3333  int fac;
-
3334  long long int index, globalIndex;
-
3335 
-
3336 # ifdef _OPENMP
-
3337 # pragma omp parallel \
-
3338  default (none) \
-
3339  shared (offset, stateVecSize, stateVecReal,stateVecImag, ctrlMask,targMask, cosAngle,sinAngle) \
-
3340  private (index,globalIndex, fac, stateReal,stateImag)
-
3341 # endif
-
3342  {
-
3343 # ifdef _OPENMP
-
3344 # pragma omp for schedule (static)
-
3345 # endif
-
3346  for (index=0; index<stateVecSize; index++) {
-
3347  stateReal = stateVecReal[index];
-
3348  stateImag = stateVecImag[index];
-
3349 
-
3350  // states with not-all-one control qubits are unmodified
-
3351  globalIndex = index + offset;
-
3352  if (ctrlMask && ((ctrlMask & globalIndex) != ctrlMask))
-
3353  continue;
-
3354 
-
3355  // odd-parity target qubits get fac_j = -1 (avoid thread divergence)
-
3356  fac = 1-2*getBitMaskParity(targMask & globalIndex);
-
3357  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3358  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3359  }
-
3360  }
-
3361 }
+

Definition at line 3358 of file QuEST_cpu.c.

+
3359 {
+
3360  long long int offset = qureg.chunkId * qureg.numAmpsPerChunk;
+
3361 
+
3362  long long int stateVecSize = qureg.numAmpsPerChunk;
+
3363  qreal *stateVecReal = qureg.stateVec.real;
+
3364  qreal *stateVecImag = qureg.stateVec.imag;
+
3365 
+
3366  qreal stateReal, stateImag;
+
3367  qreal cosAngle = cos(angle/2.0);
+
3368  qreal sinAngle = sin(angle/2.0);
+
3369 
+
3370  // = +-1, to flip sinAngle based on target qubit parity, to effect
+
3371  // exp(-angle/2 i fac_j)|j>
+
3372  int fac;
+
3373  long long int index, globalIndex;
+
3374 
+
3375 # ifdef _OPENMP
+
3376 # pragma omp parallel \
+
3377  default (none) \
+
3378  shared (offset, stateVecSize, stateVecReal,stateVecImag, ctrlMask,targMask, cosAngle,sinAngle) \
+
3379  private (index,globalIndex, fac, stateReal,stateImag)
+
3380 # endif
+
3381  {
+
3382 # ifdef _OPENMP
+
3383 # pragma omp for schedule (static)
+
3384 # endif
+
3385  for (index=0; index<stateVecSize; index++) {
+
3386  stateReal = stateVecReal[index];
+
3387  stateImag = stateVecImag[index];
+
3388 
+
3389  // states with not-all-one control qubits are unmodified
+
3390  globalIndex = index + offset;
+
3391  if (ctrlMask && ((ctrlMask & globalIndex) != ctrlMask))
+
3392  continue;
+
3393 
+
3394  // odd-parity target qubits get fac_j = -1 (avoid thread divergence)
+
3395  fac = 1-2*getBitMaskParity(targMask & globalIndex);
+
3396  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
3397  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
3398  }
+
3399  }
+
3400 }
-

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by multiControlledMultiRotateZ(), and statevec_multiControlledMultiRotatePauli().

+

Referenced by multiControlledMultiRotateZ(), and statevec_multiControlledMultiRotatePauli().

@@ -6515,42 +6540,42 @@

-

Definition at line 3678 of file QuEST_cpu.c.

-
3679 {
-
3680  long long int index;
-
3681  long long int stateVecSize;
-
3682 
-
3683  long long int chunkSize=qureg.numAmpsPerChunk;
-
3684  long long int chunkId=qureg.chunkId;
-
3685 
-
3686  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3687 
-
3688  stateVecSize = qureg.numAmpsPerChunk;
-
3689  qreal *stateVecReal = qureg.stateVec.real;
-
3690  qreal *stateVecImag = qureg.stateVec.imag;
-
3691 
-
3692 # ifdef _OPENMP
-
3693 # pragma omp parallel \
-
3694  default (none) \
-
3695  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
-
3696  private (index)
-
3697 # endif
-
3698  {
-
3699 # ifdef _OPENMP
-
3700 # pragma omp for schedule (static)
-
3701 # endif
-
3702  for (index=0; index<stateVecSize; index++) {
-
3703  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3704  stateVecReal [index] = - stateVecReal [index];
-
3705  stateVecImag [index] = - stateVecImag [index];
-
3706  }
-
3707  }
-
3708  }
-
3709 }
+

Definition at line 3718 of file QuEST_cpu.c.

+
3719 {
+
3720  long long int index;
+
3721  long long int stateVecSize;
+
3722 
+
3723  long long int chunkSize=qureg.numAmpsPerChunk;
+
3724  long long int chunkId=qureg.chunkId;
+
3725 
+
3726  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
3727 
+
3728  stateVecSize = qureg.numAmpsPerChunk;
+
3729  qreal *stateVecReal = qureg.stateVec.real;
+
3730  qreal *stateVecImag = qureg.stateVec.imag;
+
3731 
+
3732 # ifdef _OPENMP
+
3733 # pragma omp parallel \
+
3734  default (none) \
+
3735  shared (stateVecSize, stateVecReal,stateVecImag, mask, chunkId,chunkSize ) \
+
3736  private (index)
+
3737 # endif
+
3738  {
+
3739 # ifdef _OPENMP
+
3740 # pragma omp for schedule (static)
+
3741 # endif
+
3742  for (index=0; index<stateVecSize; index++) {
+
3743  if (mask == (mask & (index+chunkId*chunkSize)) ){
+
3744  stateVecReal [index] = - stateVecReal [index];
+
3745  stateVecImag [index] = - stateVecImag [index];
+
3746  }
+
3747  }
+
3748  }
+
3749 }

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by multiControlledPhaseFlip().

+

Referenced by multiControlledPhaseFlip().

@@ -6592,50 +6617,50 @@

-

Definition at line 3227 of file QuEST_cpu.c.

-
3228 {
-
3229  long long int index;
-
3230  long long int stateVecSize;
-
3231 
-
3232  long long int chunkSize=qureg.numAmpsPerChunk;
-
3233  long long int chunkId=qureg.chunkId;
-
3234 
-
3235  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
-
3236 
-
3237  stateVecSize = qureg.numAmpsPerChunk;
-
3238  qreal *stateVecReal = qureg.stateVec.real;
-
3239  qreal *stateVecImag = qureg.stateVec.imag;
-
3240 
-
3241  qreal stateRealLo, stateImagLo;
-
3242  qreal cosAngle = cos(angle);
-
3243  qreal sinAngle = sin(angle);
-
3244 
-
3245 # ifdef _OPENMP
-
3246 # pragma omp parallel \
-
3247  default (none) \
-
3248  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3249  private (index, stateRealLo, stateImagLo)
-
3250 # endif
-
3251  {
-
3252 # ifdef _OPENMP
-
3253 # pragma omp for schedule (static)
-
3254 # endif
-
3255  for (index=0; index<stateVecSize; index++) {
-
3256  if (mask == (mask & (index+chunkId*chunkSize)) ){
-
3257 
-
3258  stateRealLo = stateVecReal[index];
-
3259  stateImagLo = stateVecImag[index];
-
3260 
-
3261  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3262  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3263  }
-
3264  }
-
3265  }
-
3266 }
+

Definition at line 3266 of file QuEST_cpu.c.

+
3267 {
+
3268  long long int index;
+
3269  long long int stateVecSize;
+
3270 
+
3271  long long int chunkSize=qureg.numAmpsPerChunk;
+
3272  long long int chunkId=qureg.chunkId;
+
3273 
+
3274  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
+
3275 
+
3276  stateVecSize = qureg.numAmpsPerChunk;
+
3277  qreal *stateVecReal = qureg.stateVec.real;
+
3278  qreal *stateVecImag = qureg.stateVec.imag;
+
3279 
+
3280  qreal stateRealLo, stateImagLo;
+
3281  qreal cosAngle = cos(angle);
+
3282  qreal sinAngle = sin(angle);
+
3283 
+
3284 # ifdef _OPENMP
+
3285 # pragma omp parallel \
+
3286  default (none) \
+
3287  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
+
3288  private (index, stateRealLo, stateImagLo)
+
3289 # endif
+
3290  {
+
3291 # ifdef _OPENMP
+
3292 # pragma omp for schedule (static)
+
3293 # endif
+
3294  for (index=0; index<stateVecSize; index++) {
+
3295  if (mask == (mask & (index+chunkId*chunkSize)) ){
+
3296 
+
3297  stateRealLo = stateVecReal[index];
+
3298  stateImagLo = stateVecImag[index];
+
3299 
+
3300  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3301  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3302  }
+
3303  }
+
3304  }
+
3305 }

References Qureg::chunkId, getQubitBitMask(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by multiControlledPhaseShift().

+

Referenced by multiControlledPhaseShift().

@@ -6689,58 +6714,58 @@

the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

-

Definition at line 1447 of file QuEST_cpu_distributed.c.

-
1447  {
-
1448  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
-
1449  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
-
1450 
-
1451  if (q1FitsInNode && q2FitsInNode) {
-
1452  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
-
1453 
-
1454  } else if (q1FitsInNode) {
-
1455  int qSwap = (q1 > 0)? q1-1 : q1+1;
-
1456 
-
1457  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
-
1458  if (maskContainsBit(ctrlMask, qSwap))
-
1459  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
-
1460 
-
1461  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1462  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
-
1463  statevec_swapQubitAmps(qureg, q2, qSwap);
-
1464 
-
1465  } else if (q2FitsInNode) {
-
1466  int qSwap = (q2 > 0)? q2-1 : q2+1;
-
1467 
+

Definition at line 1458 of file QuEST_cpu_distributed.c.

+
1458  {
+
1459  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
+
1460  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
+
1461 
+
1462  if (q1FitsInNode && q2FitsInNode) {
+
1463  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
+
1464 
+
1465  } else if (q1FitsInNode) {
+
1466  int qSwap = (q1 > 0)? q1-1 : q1+1;
+
1467 
1468  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
1469  if (maskContainsBit(ctrlMask, qSwap))
-
1470  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
-
1471 
-
1472  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1473  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
-
1474  statevec_swapQubitAmps(qureg, q1, qSwap);
-
1475 
-
1476  } else {
-
1477  // we know with certainty that both q1 and q2 >= 2
-
1478  int swap1 = 0;
-
1479  int swap2 = 1;
-
1480 
-
1481  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
-
1482  if (maskContainsBit(ctrlMask, swap1))
-
1483  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
-
1484  if (maskContainsBit(ctrlMask, swap2))
-
1485  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
+
1470  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
+
1471 
+
1472  statevec_swapQubitAmps(qureg, q2, qSwap);
+
1473  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
+
1474  statevec_swapQubitAmps(qureg, q2, qSwap);
+
1475 
+
1476  } else if (q2FitsInNode) {
+
1477  int qSwap = (q2 > 0)? q2-1 : q2+1;
+
1478 
+
1479  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
+
1480  if (maskContainsBit(ctrlMask, qSwap))
+
1481  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
+
1482 
+
1483  statevec_swapQubitAmps(qureg, q1, qSwap);
+
1484  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
+
1485  statevec_swapQubitAmps(qureg, q1, qSwap);
1486 
-
1487  statevec_swapQubitAmps(qureg, q1, swap1);
-
1488  statevec_swapQubitAmps(qureg, q2, swap2);
-
1489  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
-
1490  statevec_swapQubitAmps(qureg, q1, swap1);
-
1491  statevec_swapQubitAmps(qureg, q2, swap2);
-
1492  }
-
1493 }
+
1487  } else {
+
1488  // we know with certainty that both q1 and q2 >= 2
+
1489  int swap1 = 0;
+
1490  int swap2 = 1;
+
1491 
+
1492  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
+
1493  if (maskContainsBit(ctrlMask, swap1))
+
1494  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
+
1495  if (maskContainsBit(ctrlMask, swap2))
+
1496  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
+
1497 
+
1498  statevec_swapQubitAmps(qureg, q1, swap1);
+
1499  statevec_swapQubitAmps(qureg, q2, swap2);
+
1500  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
+
1501  statevec_swapQubitAmps(qureg, q1, swap1);
+
1502  statevec_swapQubitAmps(qureg, q2, swap2);
+
1503  }
+
1504 }
-

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, qreal, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

+

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, qreal, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

-

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

+

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

@@ -6788,47 +6813,47 @@

-

Definition at line 1007 of file QuEST_cpu_distributed.c.

-
1008 {
-
1009  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1010  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1011  Complex rot1, rot2;
-
1012 
-
1013  // rank's chunk is in upper half of block
-
1014  int rankIsUpper;
-
1015  int pairRank; // rank of corresponding chunk
+

Definition at line 1011 of file QuEST_cpu_distributed.c.

+
1012 {
+
1013  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1014  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1015  Complex rot1, rot2;
1016 
-
1017  if (useLocalDataOnly){
-
1018  // all values required to update state vector lie in this rank
-
1019  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
-
1020  } else {
-
1021  // need to get corresponding chunk of state vector from other rank
-
1022  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1023  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
1024  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1025 
-
1026  // get corresponding values from my pair
-
1027  exchangeStateVectors(qureg, pairRank);
-
1028 
-
1029  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
-
1030  // in the correct order
-
1031  if (rankIsUpper){
-
1032  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1033  qureg.stateVec, //upper
-
1034  qureg.pairStateVec, //lower
-
1035  qureg.stateVec); //output
-
1036  } else {
-
1037  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
-
1038  qureg.pairStateVec, //upper
-
1039  qureg.stateVec, //lower
-
1040  qureg.stateVec); //output
-
1041  }
-
1042  }
-
1043 }
+
1017  // rank's chunk is in upper half of block
+
1018  int rankIsUpper;
+
1019  int pairRank; // rank of corresponding chunk
+
1020 
+
1021  if (useLocalDataOnly){
+
1022  // all values required to update state vector lie in this rank
+
1023  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
+
1024  } else {
+
1025  // need to get corresponding chunk of state vector from other rank
+
1026  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1027  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
1028  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1029 
+
1030  // get corresponding values from my pair
+
1031  exchangeStateVectors(qureg, pairRank);
+
1032 
+
1033  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
+
1034  // in the correct order
+
1035  if (rankIsUpper){
+
1036  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
+
1037  qureg.stateVec, //upper
+
1038  qureg.pairStateVec, //lower
+
1039  qureg.stateVec); //output
+
1040  } else {
+
1041  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
+
1042  qureg.pairStateVec, //upper
+
1043  qureg.stateVec, //lower
+
1044  qureg.stateVec); //output
+
1045  }
+
1046  }
+
1047 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

-

Referenced by multiControlledUnitary(), multiStateControlledUnitary(), and statevec_multiControlledMultiRotatePauli().

+

Referenced by multiControlledUnitary(), multiStateControlledUnitary(), and statevec_multiControlledMultiRotatePauli().

@@ -6870,16 +6895,16 @@

-

Definition at line 583 of file QuEST_common.c.

-
583  {
-
584 
-
585  long long int ctrlMask = 0;
-
586  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
-
587 }
+

Definition at line 573 of file QuEST_common.c.

+
573  {
+
574 
+
575  long long int ctrlMask = 0;
+
576  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
+
577 }
-

References statevec_multiControlledMultiQubitUnitary().

+

References statevec_multiControlledMultiQubitUnitary().

-

Referenced by applyMatrixN(), and multiQubitUnitary().

+

Referenced by applyMatrixN(), and multiQubitUnitary().

@@ -6935,46 +6960,46 @@

Definition at line 424 of file QuEST_common.c.

-
427  {
-
428  qreal fac = 1/sqrt(2);
-
429  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
-
430  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
-
431  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
-
432  Complex uRyBeta = {.real = -fac, .imag = 0};
-
433 
-
434  // mask may be modified to remove superfluous Identity ops
-
435  long long int mask = getQubitBitMask(targetQubits, numTargets);
-
436 
-
437  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
-
438  for (int t=0; t < numTargets; t++) {
-
439  if (targetPaulis[t] == PAULI_I)
-
440  mask -= 1LL << targetQubits[t]; // remove target from mask
-
441  if (targetPaulis[t] == PAULI_X)
-
442  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
443  if (targetPaulis[t] == PAULI_Y)
-
444  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
445  // (targetPaulis[t] == 3) is Z basis
-
446  }
-
447 
-
448  // does nothing if there are no qubits to 'rotate'
-
449  if (mask != 0)
-
450  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
-
451 
-
452  // undo X and Y basis rotations
-
453  uRxBeta.imag *= -1;
-
454  uRyBeta.real *= -1;
-
455  for (int t=0; t < numTargets; t++) {
-
456  if (targetPaulis[t] == PAULI_X)
-
457  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
-
458  if (targetPaulis[t] == PAULI_Y)
-
459  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
-
460  }
-
461 }
+

Definition at line 414 of file QuEST_common.c.

+
417  {
+
418  qreal fac = 1/sqrt(2);
+
419  Complex uRxAlpha = {.real = fac, .imag = 0}; // Rx(pi/2)* rotates Z -> Y
+
420  Complex uRxBeta = {.real = 0, .imag = (applyConj)? fac : -fac};
+
421  Complex uRyAlpha = {.real = fac, .imag = 0}; // Ry(-pi/2) rotates Z -> X
+
422  Complex uRyBeta = {.real = -fac, .imag = 0};
+
423 
+
424  // mask may be modified to remove superfluous Identity ops
+
425  long long int mask = getQubitBitMask(targetQubits, numTargets);
+
426 
+
427  // rotate basis so that exp(Z) will effect exp(Y) and exp(X)
+
428  for (int t=0; t < numTargets; t++) {
+
429  if (targetPaulis[t] == PAULI_I)
+
430  mask -= 1LL << targetQubits[t]; // remove target from mask
+
431  if (targetPaulis[t] == PAULI_X)
+
432  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
+
433  if (targetPaulis[t] == PAULI_Y)
+
434  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
+
435  // (targetPaulis[t] == 3) is Z basis
+
436  }
+
437 
+
438  // does nothing if there are no qubits to 'rotate'
+
439  if (mask != 0)
+
440  statevec_multiRotateZ(qureg, mask, (applyConj)? -angle : angle);
+
441 
+
442  // undo X and Y basis rotations
+
443  uRxBeta.imag *= -1;
+
444  uRyBeta.real *= -1;
+
445  for (int t=0; t < numTargets; t++) {
+
446  if (targetPaulis[t] == PAULI_X)
+
447  statevec_compactUnitary(qureg, targetQubits[t], uRyAlpha, uRyBeta);
+
448  if (targetPaulis[t] == PAULI_Y)
+
449  statevec_compactUnitary(qureg, targetQubits[t], uRxAlpha, uRxBeta);
+
450  }
+
451 }
-

References getQubitBitMask(), Complex::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, Complex::real, statevec_compactUnitary(), and statevec_multiRotateZ().

+

References getQubitBitMask(), Complex::imag, PAULI_I, PAULI_X, PAULI_Y, qreal, Complex::real, statevec_compactUnitary(), and statevec_multiRotateZ().

-

Referenced by applyExponentiatedPauliHamil(), and multiRotatePauli().

+

Referenced by applyExponentiatedPauliHamil(), and multiRotatePauli().

@@ -7010,51 +7035,51 @@

-

Definition at line 3277 of file QuEST_cpu.c.

-
3278 {
-
3279  long long int index;
-
3280  long long int stateVecSize;
-
3281 
-
3282  long long int chunkSize=qureg.numAmpsPerChunk;
-
3283  long long int chunkId=qureg.chunkId;
-
3284 
-
3285  stateVecSize = qureg.numAmpsPerChunk;
-
3286  qreal *stateVecReal = qureg.stateVec.real;
-
3287  qreal *stateVecImag = qureg.stateVec.imag;
-
3288 
-
3289  qreal stateReal, stateImag;
-
3290  qreal cosAngle = cos(angle/2.0);
-
3291  qreal sinAngle = sin(angle/2.0);
-
3292 
-
3293  // = +-1, to flip sinAngle based on target qubit parity, to effect
-
3294  // exp(-angle/2 i fac_j)|j>
-
3295  int fac;
-
3296 
-
3297 # ifdef _OPENMP
-
3298 # pragma omp parallel \
-
3299  default (none) \
-
3300  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
-
3301  private (index, fac, stateReal, stateImag)
-
3302 # endif
-
3303  {
-
3304 # ifdef _OPENMP
-
3305 # pragma omp for schedule (static)
-
3306 # endif
-
3307  for (index=0; index<stateVecSize; index++) {
-
3308  stateReal = stateVecReal[index];
-
3309  stateImag = stateVecImag[index];
-
3310 
-
3311  // odd-parity target qubits get fac_j = -1
-
3312  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
-
3313  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
-
3314  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
-
3315  }
-
3316  }
-
3317 }
+

Definition at line 3316 of file QuEST_cpu.c.

+
3317 {
+
3318  long long int index;
+
3319  long long int stateVecSize;
+
3320 
+
3321  long long int chunkSize=qureg.numAmpsPerChunk;
+
3322  long long int chunkId=qureg.chunkId;
+
3323 
+
3324  stateVecSize = qureg.numAmpsPerChunk;
+
3325  qreal *stateVecReal = qureg.stateVec.real;
+
3326  qreal *stateVecImag = qureg.stateVec.imag;
+
3327 
+
3328  qreal stateReal, stateImag;
+
3329  qreal cosAngle = cos(angle/2.0);
+
3330  qreal sinAngle = sin(angle/2.0);
+
3331 
+
3332  // = +-1, to flip sinAngle based on target qubit parity, to effect
+
3333  // exp(-angle/2 i fac_j)|j>
+
3334  int fac;
+
3335 
+
3336 # ifdef _OPENMP
+
3337 # pragma omp parallel \
+
3338  default (none) \
+
3339  shared (stateVecSize, stateVecReal, stateVecImag, mask, chunkId,chunkSize,cosAngle,sinAngle) \
+
3340  private (index, fac, stateReal, stateImag)
+
3341 # endif
+
3342  {
+
3343 # ifdef _OPENMP
+
3344 # pragma omp for schedule (static)
+
3345 # endif
+
3346  for (index=0; index<stateVecSize; index++) {
+
3347  stateReal = stateVecReal[index];
+
3348  stateImag = stateVecImag[index];
+
3349 
+
3350  // odd-parity target qubits get fac_j = -1
+
3351  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
+
3352  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
+
3353  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
+
3354  }
+
3355  }
+
3356 }
-

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

+

References Qureg::chunkId, getBitMaskParity(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

+

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

@@ -7084,36 +7109,36 @@

-

Definition at line 1044 of file QuEST_cpu_distributed.c.

-
1045 {
-
1046  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1047  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1048 
-
1049  // rank's chunk is in upper half of block
-
1050  int rankIsUpper;
-
1051  int pairRank; // rank of corresponding chunk
+

Definition at line 1048 of file QuEST_cpu_distributed.c.

+
1049 {
+
1050  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1051  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1052 
-
1053  if (useLocalDataOnly){
-
1054  // all values required to update state vector lie in this rank
-
1055  statevec_pauliXLocal(qureg, targetQubit);
-
1056  } else {
-
1057  // need to get corresponding chunk of state vector from other rank
-
1058  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1059  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1060  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
-
1061  // get corresponding values from my pair
-
1062  exchangeStateVectors(qureg, pairRank);
-
1063  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
-
1064  // this rank's values with pair values
- -
1066  qureg.pairStateVec, // in
-
1067  qureg.stateVec); // out
-
1068  }
-
1069 }
+
1053  // rank's chunk is in upper half of block
+
1054  int rankIsUpper;
+
1055  int pairRank; // rank of corresponding chunk
+
1056 
+
1057  if (useLocalDataOnly){
+
1058  // all values required to update state vector lie in this rank
+
1059  statevec_pauliXLocal(qureg, targetQubit);
+
1060  } else {
+
1061  // need to get corresponding chunk of state vector from other rank
+
1062  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1063  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1064  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
+
1065  // get corresponding values from my pair
+
1066  exchangeStateVectors(qureg, pairRank);
+
1067  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
+
1068  // this rank's values with pair values
+ +
1070  qureg.pairStateVec, // in
+
1071  qureg.stateVec); // out
+
1072  }
+
1073 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliXDistributed(), and statevec_pauliXLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliXDistributed(), and statevec_pauliXLocal().

-

Referenced by pauliX(), and statevec_applyPauliProd().

+

Referenced by pauliX(), and statevec_applyPauliProd().

@@ -7143,34 +7168,34 @@

-

Definition at line 1138 of file QuEST_cpu_distributed.c.

-
1139 {
-
1140  int conjFac = 1;
-
1141 
-
1142  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1143  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1144  int rankIsUpper; // rank's chunk is in upper half of block
-
1145  int pairRank; // rank of corresponding chunk
-
1146 
-
1147  if (useLocalDataOnly){
-
1148  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1149  } else {
-
1150  // need to get corresponding chunk of state vector from other rank
-
1151  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1152  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1153  // get corresponding values from my pair
-
1154  exchangeStateVectors(qureg, pairRank);
-
1155  // this rank's values are either in the upper of lower half of the block
- -
1157  qureg.pairStateVec, // in
-
1158  qureg.stateVec, // out
-
1159  rankIsUpper, conjFac);
-
1160  }
-
1161 }
+

Definition at line 1142 of file QuEST_cpu_distributed.c.

+
1143 {
+
1144  int conjFac = 1;
+
1145 
+
1146  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1147  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1148  int rankIsUpper; // rank's chunk is in upper half of block
+
1149  int pairRank; // rank of corresponding chunk
+
1150 
+
1151  if (useLocalDataOnly){
+
1152  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
1153  } else {
+
1154  // need to get corresponding chunk of state vector from other rank
+
1155  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1156  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1157  // get corresponding values from my pair
+
1158  exchangeStateVectors(qureg, pairRank);
+
1159  // this rank's values are either in the upper of lower half of the block
+ +
1161  qureg.pairStateVec, // in
+
1162  qureg.stateVec, // out
+
1163  rankIsUpper, conjFac);
+
1164  }
+
1165 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

-

Referenced by pauliY(), and statevec_applyPauliProd().

+

Referenced by pauliY(), and statevec_applyPauliProd().

@@ -7200,34 +7225,34 @@

-

Definition at line 1163 of file QuEST_cpu_distributed.c.

-
1164 {
-
1165  int conjFac = -1;
-
1166 
-
1167  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
1168  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
1169  int rankIsUpper; // rank's chunk is in upper half of block
-
1170  int pairRank; // rank of corresponding chunk
-
1171 
-
1172  if (useLocalDataOnly){
-
1173  statevec_pauliYLocal(qureg, targetQubit, conjFac);
-
1174  } else {
-
1175  // need to get corresponding chunk of state vector from other rank
-
1176  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1177  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
1178  // get corresponding values from my pair
-
1179  exchangeStateVectors(qureg, pairRank);
-
1180  // this rank's values are either in the upper of lower half of the block
- -
1182  qureg.pairStateVec, // in
-
1183  qureg.stateVec, // out
-
1184  rankIsUpper, conjFac);
-
1185  }
-
1186 }
+

Definition at line 1167 of file QuEST_cpu_distributed.c.

+
1168 {
+
1169  int conjFac = -1;
+
1170 
+
1171  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
1172  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
1173  int rankIsUpper; // rank's chunk is in upper half of block
+
1174  int pairRank; // rank of corresponding chunk
+
1175 
+
1176  if (useLocalDataOnly){
+
1177  statevec_pauliYLocal(qureg, targetQubit, conjFac);
+
1178  } else {
+
1179  // need to get corresponding chunk of state vector from other rank
+
1180  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1181  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
1182  // get corresponding values from my pair
+
1183  exchangeStateVectors(qureg, pairRank);
+
1184  // this rank's values are either in the upper of lower half of the block
+ +
1186  qureg.pairStateVec, // in
+
1187  qureg.stateVec, // out
+
1188  rankIsUpper, conjFac);
+
1189  }
+
1190 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

-

Referenced by pauliY().

+

Referenced by pauliY().

@@ -7257,17 +7282,17 @@

-

Definition at line 271 of file QuEST_common.c.

-
271  {
-
272  Complex term;
-
273  term.real = -1;
-
274  term.imag = 0;
-
275  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
276 }
+

Definition at line 261 of file QuEST_common.c.

+
261  {
+
262  Complex term;
+
263  term.real = -1;
+
264  term.imag = 0;
+
265  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
266 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by pauliZ(), and statevec_applyPauliProd().

+

Referenced by pauliZ(), and statevec_applyPauliProd().

@@ -7303,17 +7328,17 @@

-

Definition at line 264 of file QuEST_common.c.

-
264  {
-
265  Complex term;
-
266  term.real = cos(angle);
-
267  term.imag = sin(angle);
-
268  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
269 }
+

Definition at line 254 of file QuEST_common.c.

+
254  {
+
255  Complex term;
+
256  term.real = cos(angle);
+
257  term.imag = sin(angle);
+
258  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
259 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by phaseShift().

+

Referenced by phaseShift().

@@ -7349,50 +7374,50 @@

-

Definition at line 3146 of file QuEST_cpu.c.

-
3147 {
-
3148  long long int index;
-
3149  long long int stateVecSize;
-
3150  int targetBit;
-
3151 
-
3152  long long int chunkSize=qureg.numAmpsPerChunk;
-
3153  long long int chunkId=qureg.chunkId;
-
3154 
-
3155  // dimension of the state vector
-
3156  stateVecSize = qureg.numAmpsPerChunk;
-
3157  qreal *stateVecReal = qureg.stateVec.real;
-
3158  qreal *stateVecImag = qureg.stateVec.imag;
-
3159 
-
3160  qreal stateRealLo, stateImagLo;
-
3161  qreal cosAngle = term.real;
-
3162  qreal sinAngle = term.imag;
-
3163 
-
3164 # ifdef _OPENMP
-
3165 # pragma omp parallel for \
-
3166  default (none) \
-
3167  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
-
3168  chunkId,chunkSize,targetQubit) \
-
3169  private (index,targetBit,stateRealLo,stateImagLo) \
-
3170  schedule (static)
-
3171 # endif
-
3172  for (index=0; index<stateVecSize; index++) {
-
3173 
-
3174  // update the coeff of the |1> state of the target qubit
-
3175  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
-
3176  if (targetBit) {
-
3177 
-
3178  stateRealLo = stateVecReal[index];
-
3179  stateImagLo = stateVecImag[index];
-
3180 
-
3181  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
-
3182  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
-
3183  }
-
3184  }
-
3185 }
+

Definition at line 3185 of file QuEST_cpu.c.

+
3186 {
+
3187  long long int index;
+
3188  long long int stateVecSize;
+
3189  int targetBit;
+
3190 
+
3191  long long int chunkSize=qureg.numAmpsPerChunk;
+
3192  long long int chunkId=qureg.chunkId;
+
3193 
+
3194  // dimension of the state vector
+
3195  stateVecSize = qureg.numAmpsPerChunk;
+
3196  qreal *stateVecReal = qureg.stateVec.real;
+
3197  qreal *stateVecImag = qureg.stateVec.imag;
+
3198 
+
3199  qreal stateRealLo, stateImagLo;
+
3200  qreal cosAngle = term.real;
+
3201  qreal sinAngle = term.imag;
+
3202 
+
3203 # ifdef _OPENMP
+
3204 # pragma omp parallel for \
+
3205  default (none) \
+
3206  shared (stateVecSize, stateVecReal,stateVecImag, cosAngle,sinAngle, \
+
3207  chunkId,chunkSize,targetQubit) \
+
3208  private (index,targetBit,stateRealLo,stateImagLo) \
+
3209  schedule (static)
+
3210 # endif
+
3211  for (index=0; index<stateVecSize; index++) {
+
3212 
+
3213  // update the coeff of the |1> state of the target qubit
+
3214  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
+
3215  if (targetBit) {
+
3216 
+
3217  stateRealLo = stateVecReal[index];
+
3218  stateImagLo = stateVecImag[index];
+
3219 
+
3220  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
+
3221  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
+
3222  }
+
3223  }
+
3224 }

References Qureg::chunkId, extractBit(), Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

-

Referenced by statevec_pauliZ(), statevec_phaseShift(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), and statevec_tGateConj().

+

Referenced by statevec_pauliZ(), statevec_phaseShift(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), and statevec_tGateConj().

@@ -7431,35 +7456,35 @@

Definition at line 1428 of file QuEST_cpu.c.

-
1428  {
-
1429  long long int index;
-
1430  int rank;
-
1431  if (qureg.numQubitsInStateVec<=5){
-
1432  for (rank=0; rank<qureg.numChunks; rank++){
-
1433  if (qureg.chunkId==rank){
-
1434  if (reportRank) {
-
1435  printf("Reporting state from rank %d [\n", qureg.chunkId);
-
1436  printf("real, imag\n");
-
1437  } else if (rank==0) {
-
1438  printf("Reporting state [\n");
-
1439  printf("real, imag\n");
-
1440  }
-
1441 
-
1442  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
1443  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
-
1444  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
1445  }
-
1446  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
-
1447  }
-
1448  syncQuESTEnv(env);
-
1449  }
-
1450  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
-
1451 }
+

Definition at line 1439 of file QuEST_cpu.c.

+
1439  {
+
1440  long long int index;
+
1441  int rank;
+
1442  if (qureg.numQubitsInStateVec<=5){
+
1443  for (rank=0; rank<qureg.numChunks; rank++){
+
1444  if (qureg.chunkId==rank){
+
1445  if (reportRank) {
+
1446  printf("Reporting state from rank %d [\n", qureg.chunkId);
+
1447  printf("real, imag\n");
+
1448  } else if (rank==0) {
+
1449  printf("Reporting state [\n");
+
1450  printf("real, imag\n");
+
1451  }
+
1452 
+
1453  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
1454  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
+
1455  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
1456  }
+
1457  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
+
1458  }
+
1459  syncQuESTEnv(env);
+
1460  }
+
1461  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
+
1462 }
-

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

+

References Qureg::chunkId, copyStateFromGPU(), Qureg::numAmpsPerChunk, Qureg::numChunks, Qureg::numQubitsInStateVec, Qureg::stateVec, and syncQuESTEnv().

-

Referenced by reportStateToScreen().

+

Referenced by reportStateToScreen().

@@ -7501,17 +7526,17 @@

-

Definition at line 324 of file QuEST_common.c.

-
324  {
-
325 
-
326  Complex alpha, beta;
-
327  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
328  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
329 }
+

Definition at line 314 of file QuEST_common.c.

+
314  {
+
315 
+
316  Complex alpha, beta;
+
317  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
318  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
+
319 }
-

References getComplexPairFromRotation(), and statevec_compactUnitary().

+

References getComplexPairFromRotation(), and statevec_compactUnitary().

-

Referenced by rotateAroundAxis(), statevec_rotateX(), statevec_rotateY(), and statevec_rotateZ().

+

Referenced by rotateAroundAxis(), statevec_rotateX(), statevec_rotateY(), and statevec_rotateZ().

@@ -7553,19 +7578,19 @@

-

Definition at line 331 of file QuEST_common.c.

-
331  {
-
332 
-
333  Complex alpha, beta;
-
334  getComplexPairFromRotation(angle, axis, &alpha, &beta);
-
335  alpha.imag *= -1;
-
336  beta.imag *= -1;
-
337  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
-
338 }
+

Definition at line 321 of file QuEST_common.c.

+
321  {
+
322 
+
323  Complex alpha, beta;
+
324  getComplexPairFromRotation(angle, axis, &alpha, &beta);
+
325  alpha.imag *= -1;
+
326  beta.imag *= -1;
+
327  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
+
328 }
-

References getComplexPairFromRotation(), Complex::imag, and statevec_compactUnitary().

+

References getComplexPairFromRotation(), Complex::imag, and statevec_compactUnitary().

-

Referenced by rotateAroundAxis().

+

Referenced by rotateAroundAxis().

@@ -7601,16 +7626,16 @@

-

Definition at line 306 of file QuEST_common.c.

-
306  {
-
307 
-
308  Vector unitAxis = {1, 0, 0};
-
309  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
310 }
+

Definition at line 296 of file QuEST_common.c.

+
296  {
+
297 
+
298  Vector unitAxis = {1, 0, 0};
+
299  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
300 }
-

References statevec_rotateAroundAxis().

+

References statevec_rotateAroundAxis().

-

Referenced by rotateX().

+

Referenced by rotateX().

@@ -7646,16 +7671,16 @@

-

Definition at line 312 of file QuEST_common.c.

-
312  {
-
313 
-
314  Vector unitAxis = {0, 1, 0};
-
315  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
316 }
+

Definition at line 302 of file QuEST_common.c.

+
302  {
+
303 
+
304  Vector unitAxis = {0, 1, 0};
+
305  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
306 }
-

References statevec_rotateAroundAxis().

+

References statevec_rotateAroundAxis().

-

Referenced by rotateY().

+

Referenced by rotateY().

@@ -7691,16 +7716,16 @@

-

Definition at line 318 of file QuEST_common.c.

-
318  {
-
319 
-
320  Vector unitAxis = {0, 0, 1};
-
321  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
-
322 }
+

Definition at line 308 of file QuEST_common.c.

+
308  {
+
309 
+
310  Vector unitAxis = {0, 0, 1};
+
311  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
+
312 }
-

References statevec_rotateAroundAxis().

+

References statevec_rotateAroundAxis().

-

Referenced by rotateZ().

+

Referenced by rotateZ().

@@ -7748,52 +7773,52 @@

-

Definition at line 1237 of file QuEST_cpu.c.

-
1237  {
-
1238 
-
1239  /* this is actually distributed, since the user's code runs on every node */
-
1240 
-
1241  // local start/end indices of the given amplitudes, assuming they fit in this chunk
-
1242  // these may be negative or above qureg.numAmpsPerChunk
-
1243  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
-
1244  long long int localEndInd = localStartInd + numAmps; // exclusive
-
1245 
-
1246  // add this to a local index to get corresponding elem in reals & imags
-
1247  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
-
1248 
-
1249  // restrict these indices to fit into this chunk
-
1250  if (localStartInd < 0)
-
1251  localStartInd = 0;
-
1252  if (localEndInd > qureg.numAmpsPerChunk)
-
1253  localEndInd = qureg.numAmpsPerChunk;
-
1254  // they may now be out of order = no iterations
-
1255 
-
1256  // unpacking OpenMP vars
-
1257  long long int index;
-
1258  qreal* vecRe = qureg.stateVec.real;
-
1259  qreal* vecIm = qureg.stateVec.imag;
-
1260 
-
1261 # ifdef _OPENMP
-
1262 # pragma omp parallel \
-
1263  default (none) \
-
1264  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
-
1265  private (index)
-
1266 # endif
-
1267  {
-
1268 # ifdef _OPENMP
-
1269 # pragma omp for schedule (static)
-
1270 # endif
-
1271  // iterate these local inds - this might involve no iterations
-
1272  for (index=localStartInd; index < localEndInd; index++) {
-
1273  vecRe[index] = reals[index + offset];
-
1274  vecIm[index] = imags[index + offset];
-
1275  }
-
1276  }
-
1277 }
+

Definition at line 1248 of file QuEST_cpu.c.

+
1248  {
+
1249 
+
1250  /* this is actually distributed, since the user's code runs on every node */
+
1251 
+
1252  // local start/end indices of the given amplitudes, assuming they fit in this chunk
+
1253  // these may be negative or above qureg.numAmpsPerChunk
+
1254  long long int localStartInd = startInd - qureg.chunkId*qureg.numAmpsPerChunk;
+
1255  long long int localEndInd = localStartInd + numAmps; // exclusive
+
1256 
+
1257  // add this to a local index to get corresponding elem in reals & imags
+
1258  long long int offset = qureg.chunkId*qureg.numAmpsPerChunk - startInd;
+
1259 
+
1260  // restrict these indices to fit into this chunk
+
1261  if (localStartInd < 0)
+
1262  localStartInd = 0;
+
1263  if (localEndInd > qureg.numAmpsPerChunk)
+
1264  localEndInd = qureg.numAmpsPerChunk;
+
1265  // they may now be out of order = no iterations
+
1266 
+
1267  // unpacking OpenMP vars
+
1268  long long int index;
+
1269  qreal* vecRe = qureg.stateVec.real;
+
1270  qreal* vecIm = qureg.stateVec.imag;
+
1271 
+
1272 # ifdef _OPENMP
+
1273 # pragma omp parallel \
+
1274  default (none) \
+
1275  shared (localStartInd,localEndInd, vecRe,vecIm, reals,imags, offset) \
+
1276  private (index)
+
1277 # endif
+
1278  {
+
1279 # ifdef _OPENMP
+
1280 # pragma omp for schedule (static)
+
1281 # endif
+
1282  // iterate these local inds - this might involve no iterations
+
1283  for (index=localStartInd; index < localEndInd; index++) {
+
1284  vecRe[index] = reals[index + offset];
+
1285  vecIm[index] = imags[index + offset];
+
1286  }
+
1287  }
+
1288 }

References Qureg::chunkId, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

-

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

+

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

@@ -7847,52 +7872,52 @@

-

Definition at line 3965 of file QuEST_cpu.c.

-
3965  {
-
3966 
-
3967  long long int numAmps = qureg1.numAmpsPerChunk;
-
3968 
-
3969  qreal *vecRe1 = qureg1.stateVec.real;
-
3970  qreal *vecIm1 = qureg1.stateVec.imag;
-
3971  qreal *vecRe2 = qureg2.stateVec.real;
-
3972  qreal *vecIm2 = qureg2.stateVec.imag;
-
3973  qreal *vecReOut = out.stateVec.real;
-
3974  qreal *vecImOut = out.stateVec.imag;
-
3975 
-
3976  qreal facRe1 = fac1.real;
-
3977  qreal facIm1 = fac1.imag;
-
3978  qreal facRe2 = fac2.real;
-
3979  qreal facIm2 = fac2.imag;
-
3980  qreal facReOut = facOut.real;
-
3981  qreal facImOut = facOut.imag;
-
3982 
-
3983  qreal re1,im1, re2,im2, reOut,imOut;
-
3984  long long int index;
-
3985 
-
3986 # ifdef _OPENMP
-
3987 # pragma omp parallel \
-
3988  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
-
3989  private (index, re1,im1, re2,im2, reOut,imOut)
-
3990 # endif
-
3991  {
-
3992 # ifdef _OPENMP
-
3993 # pragma omp for schedule (static)
-
3994 # endif
-
3995  for (index=0LL; index<numAmps; index++) {
-
3996  re1 = vecRe1[index]; im1 = vecIm1[index];
-
3997  re2 = vecRe2[index]; im2 = vecIm2[index];
-
3998  reOut = vecReOut[index];
-
3999  imOut = vecImOut[index];
-
4000 
-
4001  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
-
4002  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
-
4003  }
-
4004  }
-
4005 }
+

Definition at line 4005 of file QuEST_cpu.c.

+
4005  {
+
4006 
+
4007  long long int numAmps = qureg1.numAmpsPerChunk;
+
4008 
+
4009  qreal *vecRe1 = qureg1.stateVec.real;
+
4010  qreal *vecIm1 = qureg1.stateVec.imag;
+
4011  qreal *vecRe2 = qureg2.stateVec.real;
+
4012  qreal *vecIm2 = qureg2.stateVec.imag;
+
4013  qreal *vecReOut = out.stateVec.real;
+
4014  qreal *vecImOut = out.stateVec.imag;
+
4015 
+
4016  qreal facRe1 = fac1.real;
+
4017  qreal facIm1 = fac1.imag;
+
4018  qreal facRe2 = fac2.real;
+
4019  qreal facIm2 = fac2.imag;
+
4020  qreal facReOut = facOut.real;
+
4021  qreal facImOut = facOut.imag;
+
4022 
+
4023  qreal re1,im1, re2,im2, reOut,imOut;
+
4024  long long int index;
+
4025 
+
4026 # ifdef _OPENMP
+
4027 # pragma omp parallel \
+
4028  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
+
4029  private (index, re1,im1, re2,im2, reOut,imOut)
+
4030 # endif
+
4031  {
+
4032 # ifdef _OPENMP
+
4033 # pragma omp for schedule (static)
+
4034 # endif
+
4035  for (index=0LL; index<numAmps; index++) {
+
4036  re1 = vecRe1[index]; im1 = vecIm1[index];
+
4037  re2 = vecRe2[index]; im2 = vecIm2[index];
+
4038  reOut = vecReOut[index];
+
4039  imOut = vecImOut[index];
+
4040 
+
4041  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
+
4042  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
+
4043  }
+
4044  }
+
4045 }

References Complex::imag, Qureg::numAmpsPerChunk, qreal, Complex::real, and Qureg::stateVec.

-

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

+

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

@@ -7922,17 +7947,17 @@

-

Definition at line 278 of file QuEST_common.c.

-
278  {
-
279  Complex term;
-
280  term.real = 0;
-
281  term.imag = 1;
-
282  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
283 }
+

Definition at line 268 of file QuEST_common.c.

+
268  {
+
269  Complex term;
+
270  term.real = 0;
+
271  term.imag = 1;
+
272  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
273 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by sGate().

+

Referenced by sGate().

@@ -7962,17 +7987,17 @@

-

Definition at line 292 of file QuEST_common.c.

-
292  {
-
293  Complex term;
-
294  term.real = 0;
-
295  term.imag = -1;
-
296  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
297 }
+

Definition at line 282 of file QuEST_common.c.

+
282  {
+
283  Complex term;
+
284  term.real = 0;
+
285  term.imag = -1;
+
286  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
287 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by sGate().

+

Referenced by sGate().

@@ -8008,23 +8033,23 @@

-

Definition at line 397 of file QuEST_common.c.

-
397  {
-
398 
-
399  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
400  u.real[0][0]=1;
-
401  u.real[3][3]=1;
-
402  u.real[1][1] = .5; u.imag[1][1] = .5;
-
403  u.real[1][2] = .5; u.imag[1][2] =-.5;
-
404  u.real[2][1] = .5; u.imag[2][1] =-.5;
-
405  u.real[2][2] = .5; u.imag[2][2] = .5;
-
406 
-
407  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
408 }
+

Definition at line 387 of file QuEST_common.c.

+
387  {
+
388 
+
389  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
+
390  u.real[0][0]=1;
+
391  u.real[3][3]=1;
+
392  u.real[1][1] = .5; u.imag[1][1] = .5;
+
393  u.real[1][2] = .5; u.imag[1][2] =-.5;
+
394  u.real[2][1] = .5; u.imag[2][1] =-.5;
+
395  u.real[2][2] = .5; u.imag[2][2] = .5;
+
396 
+
397  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
+
398 }
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

+

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

-

Referenced by sqrtSwapGate().

+

Referenced by sqrtSwapGate().

@@ -8060,23 +8085,23 @@

-

Definition at line 410 of file QuEST_common.c.

-
410  {
-
411 
-
412  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
-
413  u.real[0][0]=1;
-
414  u.real[3][3]=1;
-
415  u.real[1][1] = .5; u.imag[1][1] =-.5;
-
416  u.real[1][2] = .5; u.imag[1][2] = .5;
-
417  u.real[2][1] = .5; u.imag[2][1] = .5;
-
418  u.real[2][2] = .5; u.imag[2][2] =-.5;
-
419 
-
420  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
-
421 }
+

Definition at line 400 of file QuEST_common.c.

+
400  {
+
401 
+
402  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
+
403  u.real[0][0]=1;
+
404  u.real[3][3]=1;
+
405  u.real[1][1] = .5; u.imag[1][1] =-.5;
+
406  u.real[1][2] = .5; u.imag[1][2] = .5;
+
407  u.real[2][1] = .5; u.imag[2][1] = .5;
+
408  u.real[2][2] = .5; u.imag[2][2] =-.5;
+
409 
+
410  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
+
411 }
-

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

+

References ComplexMatrix4::imag, ComplexMatrix4::real, and statevec_twoQubitUnitary().

-

Referenced by sqrtSwapGate().

+

Referenced by sqrtSwapGate().

@@ -8112,28 +8137,28 @@

-

Definition at line 1420 of file QuEST_cpu_distributed.c.

-
1420  {
-
1421 
-
1422  // perform locally if possible
-
1423  int qbBig = (qb1 > qb2)? qb1 : qb2;
-
1424  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
-
1425  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
-
1426 
-
1427  // do nothing if this node contains no amplitudes to swap
-
1428  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
-
1429  if (oddParityGlobalInd == -1)
-
1430  return;
-
1431 
-
1432  // determine and swap amps with pair node
-
1433  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
-
1434  exchangeStateVectors(qureg, pairRank);
-
1435  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
-
1436 }
+

Definition at line 1431 of file QuEST_cpu_distributed.c.

+
1431  {
+
1432 
+
1433  // perform locally if possible
+
1434  int qbBig = (qb1 > qb2)? qb1 : qb2;
+
1435  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
+
1436  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
+
1437 
+
1438  // do nothing if this node contains no amplitudes to swap
+
1439  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
+
1440  if (oddParityGlobalInd == -1)
+
1441  return;
+
1442 
+
1443  // determine and swap amps with pair node
+
1444  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
+
1445  exchangeStateVectors(qureg, pairRank);
+
1446  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
+
1447 }
-

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, qreal, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

+

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, qreal, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

-

Referenced by agnostic_applyQFT(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledTwoQubitUnitary(), and swapGate().

+

Referenced by agnostic_applyQFT(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledTwoQubitUnitary(), and swapGate().

@@ -8163,17 +8188,17 @@

-

Definition at line 285 of file QuEST_common.c.

-
285  {
-
286  Complex term;
-
287  term.real = 1/sqrt(2);
-
288  term.imag = 1/sqrt(2);
-
289  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
290 }
+

Definition at line 275 of file QuEST_common.c.

+
275  {
+
276  Complex term;
+
277  term.real = 1/sqrt(2);
+
278  term.imag = 1/sqrt(2);
+
279  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
280 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by tGate().

+

Referenced by tGate().

@@ -8203,17 +8228,17 @@

-

Definition at line 299 of file QuEST_common.c.

-
299  {
-
300  Complex term;
-
301  term.real = 1/sqrt(2);
-
302  term.imag = -1/sqrt(2);
-
303  statevec_phaseShiftByTerm(qureg, targetQubit, term);
-
304 }
+

Definition at line 289 of file QuEST_common.c.

+
289  {
+
290  Complex term;
+
291  term.real = 1/sqrt(2);
+
292  term.imag = -1/sqrt(2);
+
293  statevec_phaseShiftByTerm(qureg, targetQubit, term);
+
294 }
-

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

+

References Complex::imag, Complex::real, and statevec_phaseShiftByTerm().

-

Referenced by tGate().

+

Referenced by tGate().

@@ -8255,16 +8280,16 @@

-

Definition at line 571 of file QuEST_common.c.

-
571  {
-
572 
-
573  long long int ctrlMask = 0;
-
574  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
-
575 }
+

Definition at line 561 of file QuEST_common.c.

+
561  {
+
562 
+
563  long long int ctrlMask = 0;
+
564  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
+
565 }
-

References statevec_multiControlledTwoQubitUnitary().

+

References statevec_multiControlledTwoQubitUnitary().

-

Referenced by applyMatrix4(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and twoQubitUnitary().

+

Referenced by applyMatrix4(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and twoQubitUnitary().

@@ -8300,48 +8325,48 @@

-

Definition at line 891 of file QuEST_cpu_distributed.c.

-
892 {
-
893  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
-
894  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
-
895  Complex rot1, rot2;
-
896 
-
897  // rank's chunk is in upper half of block
-
898  int rankIsUpper;
-
899  int pairRank; // rank of corresponding chunk
+

Definition at line 895 of file QuEST_cpu_distributed.c.

+
896 {
+
897  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
+
898  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
+
899  Complex rot1, rot2;
900 
-
901  if (useLocalDataOnly){
-
902  // all values required to update state vector lie in this rank
-
903  statevec_unitaryLocal(qureg, targetQubit, u);
-
904  } else {
-
905  // need to get corresponding chunk of state vector from other rank
-
906  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
907  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
-
908  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
-
909  // get corresponding values from my pair
-
910  exchangeStateVectors(qureg, pairRank);
-
911 
-
912  // this rank's values are either in the upper of lower half of the block.
-
913  // send values to compactUnitaryDistributed in the correct order
-
914  if (rankIsUpper){
-
915  statevec_unitaryDistributed(qureg,rot1,rot2,
-
916  qureg.stateVec, //upper
-
917  qureg.pairStateVec, //lower
-
918  qureg.stateVec); //output
-
919  } else {
-
920  statevec_unitaryDistributed(qureg,rot1,rot2,
-
921  qureg.pairStateVec, //upper
-
922  qureg.stateVec, //lower
-
923  qureg.stateVec); //output
-
924  }
-
925  }
-
926 
-
927 
-
928 }
+
901  // rank's chunk is in upper half of block
+
902  int rankIsUpper;
+
903  int pairRank; // rank of corresponding chunk
+
904 
+
905  if (useLocalDataOnly){
+
906  // all values required to update state vector lie in this rank
+
907  statevec_unitaryLocal(qureg, targetQubit, u);
+
908  } else {
+
909  // need to get corresponding chunk of state vector from other rank
+
910  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
911  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
+
912  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
+
913  // get corresponding values from my pair
+
914  exchangeStateVectors(qureg, pairRank);
+
915 
+
916  // this rank's values are either in the upper of lower half of the block.
+
917  // send values to compactUnitaryDistributed in the correct order
+
918  if (rankIsUpper){
+
919  statevec_unitaryDistributed(qureg,rot1,rot2,
+
920  qureg.stateVec, //upper
+
921  qureg.pairStateVec, //lower
+
922  qureg.stateVec); //output
+
923  } else {
+
924  statevec_unitaryDistributed(qureg,rot1,rot2,
+
925  qureg.pairStateVec, //upper
+
926  qureg.stateVec, //lower
+
927  qureg.stateVec); //output
+
928  }
+
929  }
+
930 
+
931 
+
932 }
-

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

+

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

-

Referenced by applyMatrix2(), and unitary().

+

Referenced by applyMatrix2(), and unitary().

@@ -8351,192 +8376,192 @@

pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:99
qreal real[4][4]
Definition: QuEST.h:177
-
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:654
-
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2640
-
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
+
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
+
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:644
+
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
+
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
@ PAULI_Z
Definition: QuEST.h:96
-
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2848
-
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:923
+
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
+
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
@ DISTANCE
Definition: QuEST.h:234
-
int rank
Definition: QuEST.h:363
-
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:621
-
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:625
-
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1356
+
int rank
Definition: QuEST.h:364
+
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:611
+
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:615
+
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1369
int numChunks
The number of nodes between which the elements of this operator are split.
Definition: QuEST.h:304
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:519
-
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3576
-
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
+
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:509
+
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
+
static int isChunkToSkipInFindPZero(int chunkId, long long int chunkSize, int measureQubit)
Find chunks to skip when calculating probability of qubit being zero.
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
@ PAULI_I
Definition: QuEST.h:96
-
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3474
-
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1335
-
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
-
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:632
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:571
+
qreal statevec_findProbabilityOfZeroDistributed(Qureg qureg)
Measure the probability of a specified qubit being in the zero state across all amplitudes held in th...
Definition: QuEST_cpu.c:3513
+
ComplexMatrixN createComplexMatrixN(int numQubits)
Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
Definition: QuEST.c:1348
+
void densmatr_mixDepolarisingDistributed(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:230
+
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:638
+
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:561
qreal z
Definition: QuEST.h:200
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
-
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3882
-
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:505
+
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
+
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:495
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
-
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3268
-
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2503
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3277
-
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2739
-
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2437
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3727
-
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
+
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3307
+
void statevec_multiControlledUnitaryDistributed(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit in the state vector of probability amplitudes,...
Definition: QuEST_cpu.c:2542
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3316
+
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
+
void statevec_controlledUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2476
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
+
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, int targetQubit, int qubit2)
int chunkId
The position of the chunk of the operator held by this process in the full operator.
Definition: QuEST.h:306
@ NORM
Definition: QuEST.h:232
-
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1743
-
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:861
+
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
+
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
@ GATE_HADAMARD
Definition: QuEST_qasm.h:26
-
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4084
+
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
Vector getUnitVector(Vector vec)
Definition: QuEST_common.c:84
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
@ UNSIGNED
Definition: QuEST.h:269
-
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1901
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
+
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:120
-
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1802
+
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
@ INVERSE_DISTANCE
Definition: QuEST.h:234
-
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2612
-
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
-
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
+
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2651
+
static int getChunkOuterBlockPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit, int numQubits)
+
void copyVecIntoMatrixPairState(Qureg matr, Qureg vec)
This copies/clones vec (a statevector) into every node's matr pairState.
#define qreal
-
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:683
-
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3510
-
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
+
#define macro_allocStackComplexMatrixN(matrix, numQubits)
Definition: QuEST_common.c:675
+
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
+
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
@ PAULI_X
Definition: QuEST.h:96
__forceinline__ __device__ long long int flipBit(const long long int number, const int bitInd)
Definition: QuEST_gpu.cu:95
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
-
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
+
static int getChunkPairId(int chunkIsUpper, int chunkId, long long int chunkSize, int targetQubit)
get position of corresponding chunk, holding values required to update values in my chunk (with chunk...
qreal densmatr_calcTotalProb(Qureg qureg)
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3847
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
+
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Definition: QuEST_cpu.c:3887
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
Definition: QuEST_qasm.c:239
qreal y
Definition: QuEST.h:200
qreal imag[2][2]
Definition: QuEST.h:140
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4406
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3319
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3358
qreal x
Definition: QuEST.h:200
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:168
-
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
+
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, int targetQubit)
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
-
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:387
+
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
-
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
-
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2943
-
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:630
-
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
+
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
+
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
+
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:620
+
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, int targetQubit, qreal retain)
Definition: QuEST_cpu.c:54
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
-
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:617
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
+
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:607
@ SCALED_PRODUCT
Definition: QuEST.h:233
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
-
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:754
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1561
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:324
-
int numRanks
Definition: QuEST.h:364
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2056
+
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:760
+
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1572
+
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:314
+
int numRanks
Definition: QuEST.h:365
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void statevec_compactUnitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2095
qreal imag[4][4]
Definition: QuEST.h:178
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void exchangeStateVectors(Qureg qureg, int pairRank)
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void exchangeStateVectors(Qureg qureg, int pairRank)
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
-
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2229
+
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
-
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:744
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:750
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
@ PAULI_Y
Definition: QuEST.h:96
-
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2906
+
void statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2945
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
-
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:300
-
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4127
-
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2554
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:340
-
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1184
+
void densmatr_mixDampingDistributed(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:306
+
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
+
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
+
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:330
+
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
__forceinline__ __device__ int extractBit(const int locationOfBitFromRight, const long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3965
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:4005
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
+
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
Definition: QuEST_common.c:161
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
@ INVERSE_NORM
Definition: QuEST.h:232
-
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:958
-
static int getChunkIdFromIndex(Qureg qureg, long long int index)
-
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2795
-
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2112
-
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2375
+
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
+
static int getChunkIdFromIndex(Qureg qureg, long long int index)
+
void statevec_multiControlledMultiQubitNotDistributed(Qureg qureg, int ctrlMask, int targMask, ComplexArray stateVecIn, ComplexArray stateVecOut)
Definition: QuEST_cpu.c:2834
+
void statevec_unitaryDistributed(Qureg qureg, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Apply a unitary operation to a single qubit given a subset of the state vector with upper and lower b...
Definition: QuEST_cpu.c:2151
+
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, int controlQubit, Complex rot1, Complex rot2, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut)
Rotate a single qubit in the state vector of probability amplitudes, given two complex numbers alpha ...
Definition: QuEST_cpu.c:2414
@ PRODUCT
Definition: QuEST.h:233
-
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
+
static int densityMatrixBlockFitsInChunk(long long int chunkSize, int numQubits, int targetQubit)
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
qreal real[2][2]
Definition: QuEST.h:139
-
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
-
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3809
-
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
+
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
+
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, int measureQubit, qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3849
+
static int halfMatrixBlockFitsInChunk(long long int chunkSize, int targetQubit)
return whether the current qubit rotation will use blocks that fit within a single chunk.
long long int numElemsPerChunk
The number of the 2^numQubits amplitudes stored on each distributed node.
Definition: QuEST.h:302
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3039
+
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
int numQubits
Definition: QuEST.h:188
-
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4042
-
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2297
-
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:636
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3146
-
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:488
-
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
+
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
+
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
+
long long int getGlobalIndOfOddParityInChunk(Qureg qureg, int qb1, int qb2)
returns -1 if this node contains no amplitudes where qb1 and qb2 have opposite parity,...
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:626
+
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3185
+
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:494
+
void copyDiagOpIntoMatrixPairState(Qureg qureg, DiagonalOp op)
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
-
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2703
+
void statevec_controlledNotDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2742
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
@ GATE_SWAP
Definition: QuEST_qasm.h:33
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
qreal real
Definition: QuEST.h:105
-
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3925
-
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:644
+
void statevec_swapQubitAmpsDistributed(Qureg qureg, int pairRank, int qb1, int qb2)
qureg.pairStateVec contains the entire set of amplitudes of the paired node which includes the set of...
Definition: QuEST_cpu.c:3965
+
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:634
qreal imag
Definition: QuEST.h:106
-
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
-
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:541
-
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1987
-
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3363
-
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
+
static int getChunkOuterBlockPairIdForPart3(int chunkIsUpperSmallerQubit, int chunkIsUpperBiggerQubit, int chunkId, long long int chunkSize, int smallerQubit, int biggerQubit, int numQubits)
+
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, int targetQubit, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:547
+
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
+
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
+
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
Represents one complex number.
Definition: QuEST.h:103
-
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3100
+
void statevec_hadamardDistributed(Qureg qureg, ComplexArray stateVecUp, ComplexArray stateVecLo, ComplexArray stateVecOut, int updateUpper)
Rotate a single qubit by {{1,1},{1,-1}}/sqrt2.
Definition: QuEST_cpu.c:3139
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
static int maskContainsBit(const long long int mask, const int bitInd)
void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
Definition: QuEST_qasm.c:179
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
#define M_PI
Definition: QuEST_common.c:41
-
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:807
-
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:2997
-
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2157
-
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
+
void applySymmetrizedTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order)
Definition: QuEST_common.c:820
+
void statevec_controlledPauliYDistributed(Qureg qureg, int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, int conjFac)
Definition: QuEST_cpu.c:3036
+
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
+
static int chunkIsUpper(int chunkId, long long int chunkSize, int targetQubit)
Returns whether a given chunk in position chunkId is in the upper or lower half of a block.
void qasm_recordNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc funcName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:726
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
-
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1071
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:734
+
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:740
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
-
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:990
-
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3418
+
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
+
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457
diff --git a/docs/QuEST__internal_8h_source.html b/docs/QuEST__internal_8h_source.html index 81106cb97..00ccc64eb 100644 --- a/docs/QuEST__internal_8h_source.html +++ b/docs/QuEST__internal_8h_source.html @@ -27,7 +27,7 @@ @@ -349,147 +349,147 @@
297 
298 # endif // QUEST_INTERNAL_H
-
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1357
-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:697
+
void agnostic_destroyDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1368
+
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
+
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:701
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:548
-
void densmatr_initPlusState(Qureg targetQureg)
Definition: QuEST_cpu.c:1154
-
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
-
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:390
-
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:397
-
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:292
-
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
-
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
+
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:538
+
void densmatr_initPlusState(Qureg targetQureg)
Definition: QuEST_cpu.c:1165
+
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
+
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:380
+
void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:387
+
void statevec_sGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:282
+
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
+
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
-
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3277
-
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1362
-
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1317
-
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
-
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3187
-
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1600
+
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3316
+
void agnostic_syncDiagonalOp(DiagonalOp op)
Definition: QuEST_cpu.c:1373
+
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1328
+
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
+
void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
Definition: QuEST_cpu.c:3226
+
void statevec_initStateOfSingleQubit(Qureg *qureg, int qubitId, int outcome)
Initialise the state vector of probability amplitudes such that one qubit is set to 'outcome' and all...
Definition: QuEST_cpu.c:1611
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1115
-
Information about the environment the program is running in.
Definition: QuEST.h:361
-
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:306
-
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3227
-
void statevec_pauliY(Qureg qureg, int targetQubit)
-
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:382
-
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:312
+
void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1126
+
Information about the environment the program is running in.
Definition: QuEST.h:362
+
void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:296
+
void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Definition: QuEST_cpu.c:3266
+
void statevec_pauliY(Qureg qureg, int targetQubit)
+
int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:372
+
void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:302
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal pX, qreal pY, qreal pZ)
Definition: QuEST_common.c:730
+
void densmatr_mixPauli(Qureg qureg, int qubit, qreal pX, qreal pY, qreal pZ)
Definition: QuEST_common.c:743
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:156
-
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:589
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:654
+
void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:579
+
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:644
#define qreal
-
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:324
-
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1335
-
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:340
-
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
-
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
-
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:331
-
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:827
-
void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
Definition: QuEST_common.c:463
+
void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:314
+
DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1346
+
void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:330
+
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
+
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
+
void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:321
+
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:840
+
void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
Definition: QuEST_common.c:453
qreal densmatr_calcTotalProb(Qureg qureg)
-
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
-
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:264
-
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:785
-
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
-
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:285
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
-
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4406
-
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3319
+
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
+
void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
Definition: QuEST_common.c:254
+
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
+
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
+
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void statevec_tGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:275
+
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:901
+
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
+
void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
Definition: QuEST_cpu.c:3358
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
-
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
Definition: QuEST_common.c:60
-
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1483
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:519
-
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
-
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:362
-
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4228
-
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1453
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1428
-
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:410
-
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4007
-
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1237
-
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1561
-
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:347
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:356
-
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
-
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1493
-
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:299
-
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
+
void statevec_initZeroState(Qureg qureg)
Definition: QuEST_cpu.c:1494
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:85
+
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:509
+
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
+
void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:352
+
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4268
+
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1464
+
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1439
+
void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
Definition: QuEST_common.c:400
+
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4047
+
void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Definition: QuEST_cpu.c:1248
+
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1572
+
void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:337
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:346
+
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
+
void statevec_initPlusState(Qureg qureg)
Definition: QuEST_cpu.c:1504
+
void statevec_tGateConj(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:289
+
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
-
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:271
+
void statevec_pauliZ(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:261
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:70
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3678
-
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
+
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
+
void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Definition: QuEST_cpu.c:3718
+
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
+
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
unsigned long int hashString(char *str)
Definition: QuEST_common.c:185
ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
Definition: QuEST_common.c:105
void setConjugateMatrixN(ComplexMatrixN m)
Definition: QuEST_common.c:115
-
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:424
+
void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
applyConj=1 will apply conjugate operation, else applyConj=0
Definition: QuEST_common.c:414
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:120
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
long long int getQubitBitMask(int *controlQubits, int numControlQubits)
Definition: QuEST_common.c:50
-
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:3965
-
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
-
qreal statevec_getImagAmp(Qureg qureg, long long int index)
+
void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Definition: QuEST_cpu.c:4005
+
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
+
qreal statevec_getImagAmp(Qureg qureg, long long int index)
Represents a system of qubits.
Definition: QuEST.h:322
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1646
-
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:278
+
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1657
+
void statevec_sGate(Qureg qureg, int targetQubit)
Definition: QuEST_common.c:268
void getComplexPairAndPhaseFromUnitary(ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)
Definition: QuEST_common.c:142
-
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
-
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_cpu.c:1366
+
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
+
void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
Definition: QuEST_cpu.c:1377
-
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:318
-
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
-
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1525
-
void statevec_hadamard(Qureg qureg, int targetQubit)
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:689
-
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
-
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:368
-
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1680
-
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3146
-
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:534
-
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:583
-
void statevec_pauliX(Qureg qureg, int targetQubit)
-
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:836
+
void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
Definition: QuEST_common.c:308
+
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
+
void statevec_initClassicalState(Qureg qureg, long long int stateInd)
Definition: QuEST_cpu.c:1536
+
void statevec_hadamard(Qureg qureg, int targetQubit)
+
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:682
+
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
+
void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
Definition: QuEST_common.c:358
+
int statevec_initStateFromSingleFile(Qureg *qureg, char filename[200], QuESTEnv env)
Definition: QuEST_cpu.c:1691
+
void statevec_phaseShiftByTerm(Qureg qureg, int targetQubit, Complex term)
Definition: QuEST_cpu.c:3185
+
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:524
+
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:573
+
void statevec_pauliX(Qureg qureg, int targetQubit)
+
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:849
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
-
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:4188
-
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3647
+
void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
Definition: QuEST_cpu.c:4228
+
void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
Definition: QuEST_cpu.c:3687
void conjugateMatrixN(ComplexMatrixN u)
-
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
-
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1730
+
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
+
int statevec_compareStates(Qureg mq1, Qureg mq2, qreal precision)
Definition: QuEST_cpu.c:1741
void getZYZRotAnglesFromComplexPair(Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)
Definition: QuEST_common.c:130
Represents one complex number.
Definition: QuEST.h:103
void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
Definition: QuEST_common.c:161
-
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:571
-
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1279
-
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
+
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:561
+
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1290
+
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
Definition: QuEST_common.c:110
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
Complex getConjugateScalar(Complex scalar)
Definition: QuEST_common.c:91
-
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:374
-
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:577
-
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
-
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:258
-
qreal statevec_getRealAmp(Qureg qureg, long long int index)
+
int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Definition: QuEST_common.c:364
+
void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:567
+
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
+
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:248
+
qreal statevec_getRealAmp(Qureg qureg, long long int index)
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
void statevec_pauliYConj(Qureg qureg, int targetQubit)
+
void statevec_pauliYConj(Qureg qureg, int targetQubit)
qreal statevec_calcTotalProb(Qureg qureg)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
-
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4305
-
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
+
void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
+
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4345
+
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
diff --git a/docs/QuEST__precision_8h.html b/docs/QuEST__precision_8h.html index 3ecbdb92d..b7c2dbc65 100644 --- a/docs/QuEST__precision_8h.html +++ b/docs/QuEST__precision_8h.html @@ -27,7 +27,7 @@ diff --git a/docs/QuEST__precision_8h_source.html b/docs/QuEST__precision_8h_source.html index f1e1beced..6e91b70d0 100644 --- a/docs/QuEST__precision_8h_source.html +++ b/docs/QuEST__precision_8h_source.html @@ -27,7 +27,7 @@ diff --git a/docs/QuEST__qasm_8c.html b/docs/QuEST__qasm_8c.html index 472ad40e3..02fd71722 100644 --- a/docs/QuEST__qasm_8c.html +++ b/docs/QuEST__qasm_8c.html @@ -27,7 +27,7 @@ @@ -986,7 +986,7 @@

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by rotateAroundAxis().

+

Referenced by rotateAroundAxis().

@@ -1043,7 +1043,7 @@

References addStringToQASM(), COMMENT_PREF, MAX_LINE_LEN, and Qureg::qasmLog.

-

Referenced by addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addShiftValuesToQASM(), applyDiagonalOp(), applyExponentiatedPauliHamil(), applyFullQFT(), applyMatrix2(), applyMatrix4(), applyMatrixN(), applyMultiControlledMatrixN(), applyPauliHamil(), applyPauliSum(), applyQFT(), applyTrotterCircuit(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), initBlankState(), initPureState(), initStateFromAmps(), mixDephasing(), mixDepolarising(), mixKrausMap(), mixMultiQubitKrausMap(), mixPauli(), mixTwoQubitDephasing(), mixTwoQubitDepolarising(), mixTwoQubitKrausMap(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordInitClassical(), qasm_recordInitPlus(), qasm_recordMultiControlledMultiQubitNot(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), qasm_recordMultiVarPhaseFunc(), qasm_recordNamedPhaseFunc(), qasm_recordPhaseFunc(), setAmps(), setDensityAmps(), setWeightedQureg(), and twoQubitUnitary().

+

Referenced by addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addShiftValuesToQASM(), applyDiagonalOp(), applyExponentiatedPauliHamil(), applyFullQFT(), applyMatrix2(), applyMatrix4(), applyMatrixN(), applyMultiControlledMatrixN(), applyPauliHamil(), applyPauliSum(), applyProjector(), applyQFT(), applyTrotterCircuit(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), initBlankState(), initPureState(), initStateFromAmps(), mixDephasing(), mixDepolarising(), mixKrausMap(), mixMultiQubitKrausMap(), mixPauli(), mixTwoQubitDephasing(), mixTwoQubitDepolarising(), mixTwoQubitKrausMap(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordInitClassical(), qasm_recordInitPlus(), qasm_recordMultiControlledMultiQubitNot(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), qasm_recordMultiVarPhaseFunc(), qasm_recordNamedPhaseFunc(), qasm_recordPhaseFunc(), setAmps(), setDensityAmps(), setWeightedQureg(), and twoQubitUnitary().

@@ -1100,7 +1100,7 @@

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by compactUnitary().

+

Referenced by compactUnitary().

@@ -1167,7 +1167,7 @@

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by controlledRotateAroundAxis().

+

Referenced by controlledRotateAroundAxis().

@@ -1231,7 +1231,7 @@

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by controlledCompactUnitary().

+

Referenced by controlledCompactUnitary().

@@ -1285,7 +1285,7 @@

References addGateToQASM(), and Qureg::qasmLog.

-

Referenced by agnostic_applyQFT(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), sqrtSwapGate(), and swapGate().

+

Referenced by agnostic_applyQFT(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), sqrtSwapGate(), and swapGate().

@@ -1353,7 +1353,7 @@

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by controlledPhaseShift(), controlledRotateX(), controlledRotateY(), and controlledRotateZ().

+

Referenced by controlledPhaseShift(), controlledRotateX(), controlledRotateY(), and controlledRotateZ().

@@ -1422,7 +1422,7 @@

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by controlledUnitary().

+

Referenced by controlledUnitary().

@@ -1469,7 +1469,7 @@

References addGateToQASM(), and Qureg::qasmLog.

-

Referenced by agnostic_applyQFT(), hadamard(), pauliX(), pauliY(), pauliZ(), qasm_recordInitClassical(), sGate(), and tGate().

+

Referenced by agnostic_applyQFT(), hadamard(), pauliX(), pauliY(), pauliZ(), qasm_recordInitClassical(), sGate(), and tGate().

@@ -1660,7 +1660,7 @@

References addStringToQASM(), bufferOverflow(), MAX_LINE_LEN, MEASURE_CMD, MESREG_LABEL, Qureg::qasmLog, and QUREG_LABEL.

-

Referenced by collapseToOutcome(), measure(), and measureWithStats().

+

Referenced by collapseToOutcome(), measure(), and measureWithStats().

@@ -1719,7 +1719,7 @@

References addGateToQASM(), and Qureg::qasmLog.

-

Referenced by multiControlledPhaseFlip().

+

Referenced by multiControlledPhaseFlip().

@@ -1782,7 +1782,7 @@

References addGateToQASM(), GATE_SIGMA_X, qasm_recordComment(), and Qureg::qasmLog.

-

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

+

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

@@ -1855,7 +1855,7 @@

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by multiControlledPhaseShift().

+

Referenced by multiControlledPhaseShift().

@@ -1929,7 +1929,7 @@

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by multiControlledUnitary(), and qasm_recordMultiStateControlledUnitary().

+

Referenced by multiControlledUnitary(), and qasm_recordMultiStateControlledUnitary().

@@ -2003,7 +2003,7 @@

References addGateToQASM(), GATE_SIGMA_X, qasm_recordComment(), qasm_recordMultiControlledUnitary(), and Qureg::qasmLog.

-

Referenced by multiStateControlledUnitary().

+

Referenced by multiStateControlledUnitary().

@@ -2150,7 +2150,7 @@

References addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addStringToQASM(), bufferOverflow(), getPhaseFuncSymbol(), MAX_LINE_LEN, MAX_REG_SYMBS, qasm_recordComment(), and Qureg::qasmLog.

-

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

@@ -2374,7 +2374,7 @@

References addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addShiftValuesToQASM(), addStringToQASM(), bufferOverflow(), DISTANCE, getPhaseFuncSymbol(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_LINE_LEN, MAX_REG_SYMBS, NORM, PRODUCT, qasm_recordComment(), Qureg::qasmLog, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, and SCALED_PRODUCT.

-

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -2428,7 +2428,7 @@

References addGateToQASM(), Qureg::qasmLog, and qreal.

-

Referenced by phaseShift(), rotateX(), rotateY(), and rotateZ().

+

Referenced by phaseShift(), rotateX(), rotateY(), and rotateZ().

@@ -2575,7 +2575,7 @@

References addStringToQASM(), bufferOverflow(), MAX_LINE_LEN, qasm_recordComment(), Qureg::qasmLog, TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -2630,7 +2630,7 @@

References addGateToQASM(), GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by unitary().

+

Referenced by unitary().

diff --git a/docs/QuEST__qasm_8c_source.html b/docs/QuEST__qasm_8c_source.html index dcf1298ef..4325490cc 100644 --- a/docs/QuEST__qasm_8c_source.html +++ b/docs/QuEST__qasm_8c_source.html @@ -27,7 +27,7 @@ diff --git a/docs/QuEST__qasm_8h.html b/docs/QuEST__qasm_8h.html index 8ab1a7522..0e8a4e2c8 100644 --- a/docs/QuEST__qasm_8h.html +++ b/docs/QuEST__qasm_8h.html @@ -27,7 +27,7 @@ @@ -356,7 +356,7 @@

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by rotateAroundAxis().

+

Referenced by rotateAroundAxis().

@@ -413,7 +413,7 @@

References addStringToQASM(), COMMENT_PREF, MAX_LINE_LEN, and Qureg::qasmLog.

-

Referenced by addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addShiftValuesToQASM(), applyDiagonalOp(), applyExponentiatedPauliHamil(), applyFullQFT(), applyMatrix2(), applyMatrix4(), applyMatrixN(), applyMultiControlledMatrixN(), applyPauliHamil(), applyPauliSum(), applyQFT(), applyTrotterCircuit(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), initBlankState(), initPureState(), initStateFromAmps(), mixDephasing(), mixDepolarising(), mixKrausMap(), mixMultiQubitKrausMap(), mixPauli(), mixTwoQubitDephasing(), mixTwoQubitDepolarising(), mixTwoQubitKrausMap(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordInitClassical(), qasm_recordInitPlus(), qasm_recordMultiControlledMultiQubitNot(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), qasm_recordMultiVarPhaseFunc(), qasm_recordNamedPhaseFunc(), qasm_recordPhaseFunc(), setAmps(), setDensityAmps(), setWeightedQureg(), and twoQubitUnitary().

+

Referenced by addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addShiftValuesToQASM(), applyDiagonalOp(), applyExponentiatedPauliHamil(), applyFullQFT(), applyMatrix2(), applyMatrix4(), applyMatrixN(), applyMultiControlledMatrixN(), applyPauliHamil(), applyPauliSum(), applyProjector(), applyQFT(), applyTrotterCircuit(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), initBlankState(), initPureState(), initStateFromAmps(), mixDephasing(), mixDepolarising(), mixKrausMap(), mixMultiQubitKrausMap(), mixPauli(), mixTwoQubitDephasing(), mixTwoQubitDepolarising(), mixTwoQubitKrausMap(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledTwoQubitUnitary(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), qasm_recordControlledParamGate(), qasm_recordControlledUnitary(), qasm_recordInitClassical(), qasm_recordInitPlus(), qasm_recordMultiControlledMultiQubitNot(), qasm_recordMultiControlledParamGate(), qasm_recordMultiControlledUnitary(), qasm_recordMultiStateControlledUnitary(), qasm_recordMultiVarPhaseFunc(), qasm_recordNamedPhaseFunc(), qasm_recordPhaseFunc(), setAmps(), setDensityAmps(), setWeightedQureg(), and twoQubitUnitary().

@@ -470,7 +470,7 @@

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by compactUnitary().

+

Referenced by compactUnitary().

@@ -537,7 +537,7 @@

References addGateToQASM(), GATE_UNITARY, getComplexPairFromRotation(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by controlledRotateAroundAxis().

+

Referenced by controlledRotateAroundAxis().

@@ -601,7 +601,7 @@

References addGateToQASM(), GATE_UNITARY, getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by controlledCompactUnitary().

+

Referenced by controlledCompactUnitary().

@@ -655,7 +655,7 @@

References addGateToQASM(), and Qureg::qasmLog.

-

Referenced by agnostic_applyQFT(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), sqrtSwapGate(), and swapGate().

+

Referenced by agnostic_applyQFT(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), sqrtSwapGate(), and swapGate().

@@ -723,7 +723,7 @@

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by controlledPhaseShift(), controlledRotateX(), controlledRotateY(), and controlledRotateZ().

+

Referenced by controlledPhaseShift(), controlledRotateX(), controlledRotateY(), and controlledRotateZ().

@@ -792,7 +792,7 @@

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by controlledUnitary().

+

Referenced by controlledUnitary().

@@ -839,7 +839,7 @@

References addGateToQASM(), and Qureg::qasmLog.

-

Referenced by agnostic_applyQFT(), hadamard(), pauliX(), pauliY(), pauliZ(), qasm_recordInitClassical(), sGate(), and tGate().

+

Referenced by agnostic_applyQFT(), hadamard(), pauliX(), pauliY(), pauliZ(), qasm_recordInitClassical(), sGate(), and tGate().

@@ -1030,7 +1030,7 @@

References addStringToQASM(), bufferOverflow(), MAX_LINE_LEN, MEASURE_CMD, MESREG_LABEL, Qureg::qasmLog, and QUREG_LABEL.

-

Referenced by collapseToOutcome(), measure(), and measureWithStats().

+

Referenced by collapseToOutcome(), measure(), and measureWithStats().

@@ -1089,7 +1089,7 @@

References addGateToQASM(), and Qureg::qasmLog.

-

Referenced by multiControlledPhaseFlip().

+

Referenced by multiControlledPhaseFlip().

@@ -1152,7 +1152,7 @@

References addGateToQASM(), GATE_SIGMA_X, qasm_recordComment(), and Qureg::qasmLog.

-

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

+

Referenced by multiControlledMultiQubitNot(), and multiQubitNot().

@@ -1225,7 +1225,7 @@

References addGateToQASM(), GATE_PHASE_SHIFT, GATE_ROTATE_Z, qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by multiControlledPhaseShift().

+

Referenced by multiControlledPhaseShift().

@@ -1299,7 +1299,7 @@

References addGateToQASM(), GATE_ROTATE_Z, GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), qasm_recordComment(), Qureg::qasmLog, and qreal.

-

Referenced by multiControlledUnitary(), and qasm_recordMultiStateControlledUnitary().

+

Referenced by multiControlledUnitary(), and qasm_recordMultiStateControlledUnitary().

@@ -1373,7 +1373,7 @@

References addGateToQASM(), GATE_SIGMA_X, qasm_recordComment(), qasm_recordMultiControlledUnitary(), and Qureg::qasmLog.

-

Referenced by multiStateControlledUnitary().

+

Referenced by multiStateControlledUnitary().

@@ -1520,7 +1520,7 @@

References addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addStringToQASM(), bufferOverflow(), getPhaseFuncSymbol(), MAX_LINE_LEN, MAX_REG_SYMBS, qasm_recordComment(), and Qureg::qasmLog.

-

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

@@ -1744,7 +1744,7 @@

References addMultiVarOverridesToQASM(), addMultiVarRegsToQASM(), addShiftValuesToQASM(), addStringToQASM(), bufferOverflow(), DISTANCE, getPhaseFuncSymbol(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_LINE_LEN, MAX_REG_SYMBS, NORM, PRODUCT, qasm_recordComment(), Qureg::qasmLog, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, and SCALED_PRODUCT.

-

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by agnostic_applyQFT(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -1798,7 +1798,7 @@

References addGateToQASM(), Qureg::qasmLog, and qreal.

-

Referenced by phaseShift(), rotateX(), rotateY(), and rotateZ().

+

Referenced by phaseShift(), rotateX(), rotateY(), and rotateZ().

@@ -1945,7 +1945,7 @@

References addStringToQASM(), bufferOverflow(), MAX_LINE_LEN, qasm_recordComment(), Qureg::qasmLog, TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -2000,7 +2000,7 @@

References addGateToQASM(), GATE_UNITARY, getComplexPairAndPhaseFromUnitary(), getZYZRotAnglesFromComplexPair(), Qureg::qasmLog, and qreal.

-

Referenced by unitary().

+

Referenced by unitary().

diff --git a/docs/QuEST__qasm_8h_source.html b/docs/QuEST__qasm_8h_source.html index 21b574c55..6c8a1bac2 100644 --- a/docs/QuEST__qasm_8h_source.html +++ b/docs/QuEST__qasm_8h_source.html @@ -27,7 +27,7 @@ diff --git a/docs/QuEST__validation_8c.html b/docs/QuEST__validation_8c.html index d6e9e9ec1..4f39f3619 100644 --- a/docs/QuEST__validation_8c.html +++ b/docs/QuEST__validation_8c.html @@ -27,7 +27,7 @@ @@ -195,8 +195,8 @@ unsigned int calcLog2 (long unsigned int num)  returns log2 of numbers which must be gauranteed to be 2^n More...
  -void exitWithError (const char *msg, const char *func) -  +void default_invalidQuESTInputError (const char *errMsg, const char *errFunc) +  void invalidQuESTInputError (const char *errMsg, const char *errFunc)  An internal function called when invalid arguments are passed to a QuEST API call, which the user can optionally override by redefining. More...
  @@ -372,7 +372,7 @@

Provides validation of user input

Author
Tyson Jones
-Ania Brown (exitWithError(), QuESTAssert(), original testing of: qubit indices, unitarity, valid collapse probability)
+Ania Brown (exitWithError(), QuESTAssert(), original testing of: qubit indices, unitarity, valid collapse probability)
Balint Koczor (Kraus maps)
@@ -430,7 +430,7 @@

return 1; \

}
-

Definition at line 278 of file QuEST_validation.c.

+

Definition at line 282 of file QuEST_validation.c.

@@ -493,7 +493,7 @@

} \
}
-

Definition at line 232 of file QuEST_validation.c.

+

Definition at line 236 of file QuEST_validation.c.

@@ -707,40 +707,40 @@

-

Definition at line 311 of file QuEST_validation.c.

-
311  {
-
312  long long int mask = 0;
-
313  long long int bit;
-
314  for (int q=0; q < numQubits; q++) {
-
315  bit = 1LL << qubits[q];
-
316  if (mask & bit)
-
317  return 0;
-
318  mask |= bit;
-
319  }
-
320  return 1;
-
321 }
+

Definition at line 315 of file QuEST_validation.c.

+
315  {
+
316  long long int mask = 0;
+
317  long long int bit;
+
318  for (int q=0; q < numQubits; q++) {
+
319  bit = 1LL << qubits[q];
+
320  if (mask & bit)
+
321  return 0;
+
322  mask |= bit;
+
323  }
+
324  return 1;
+
325 }
-

Referenced by validateMultiControls(), validateMultiQubits(), validateMultiTargets(), and validateQubitSubregs().

+

Referenced by validateMultiControls(), validateMultiQubits(), validateMultiTargets(), and validateQubitSubregs().

- -

◆ exitWithError()

+ +

◆ default_invalidQuESTInputError()

- + - + - + @@ -751,15 +751,15 @@

Definition at line 199 of file QuEST_validation.c.

-
199  {
+
199  {
200  printf("!!!\n");
-
201  printf("QuEST Error in function %s: %s\n", func, msg);
+
201  printf("QuEST Error in function %s: %s\n", errFunc, errMsg);
202  printf("!!!\n");
203  printf("exiting..\n");
204  exit(1);
205 }
-

Referenced by invalidQuESTInputError().

+

Referenced by invalidQuESTInputError().

@@ -789,14 +789,14 @@

-

Definition at line 296 of file QuEST_validation.c.

-
296  {
-
297  macro_isCompletelyPositiveMap(ops, numOps, 2);
-
298 }
+

Definition at line 300 of file QuEST_validation.c.

+
300  {
+
301  macro_isCompletelyPositiveMap(ops, numOps, 2);
+
302 }
-

References macro_isCompletelyPositiveMap.

+

References macro_isCompletelyPositiveMap.

-

Referenced by validateOneQubitKrausMap().

+

Referenced by validateOneQubitKrausMap().

@@ -826,14 +826,14 @@

-

Definition at line 299 of file QuEST_validation.c.

-
299  {
-
300  macro_isCompletelyPositiveMap(ops, numOps, 4);
-
301 }
+

Definition at line 303 of file QuEST_validation.c.

+
303  {
+
304  macro_isCompletelyPositiveMap(ops, numOps, 4);
+
305 }
-

References macro_isCompletelyPositiveMap.

+

References macro_isCompletelyPositiveMap.

-

Referenced by validateTwoQubitKrausMap().

+

Referenced by validateTwoQubitKrausMap().

@@ -863,15 +863,15 @@

-

Definition at line 302 of file QuEST_validation.c.

-
302  {
-
303  int opDim = 1 << ops[0].numQubits;
-
304  macro_isCompletelyPositiveMap(ops, numOps, opDim);
-
305 }
+

Definition at line 306 of file QuEST_validation.c.

+
306  {
+
307  int opDim = 1 << ops[0].numQubits;
+
308  macro_isCompletelyPositiveMap(ops, numOps, opDim);
+
309 }
-

References macro_isCompletelyPositiveMap, and ComplexMatrixN::numQubits.

+

References macro_isCompletelyPositiveMap, and ComplexMatrixN::numQubits.

-

Referenced by validateMultiQubitKrausMap().

+

Referenced by validateMultiQubitKrausMap().

@@ -901,18 +901,18 @@

-

Definition at line 224 of file QuEST_validation.c.

-
224  {
-
225  return ( absReal( -1
-
226  + alpha.real*alpha.real
-
227  + alpha.imag*alpha.imag
-
228  + beta.real*beta.real
-
229  + beta.imag*beta.imag) < REAL_EPS );
-
230 }
+

Definition at line 228 of file QuEST_validation.c.

+
228  {
+
229  return ( absReal( -1
+
230  + alpha.real*alpha.real
+
231  + alpha.imag*alpha.imag
+
232  + beta.real*beta.real
+
233  + beta.imag*beta.imag) < REAL_EPS );
+
234 }

References Complex::imag, and Complex::real.

-

Referenced by validateUnitaryComplexPair().

+

Referenced by validateUnitaryComplexPair().

@@ -932,10 +932,10 @@

-

Definition at line 216 of file QuEST_validation.c.

-
216  {
-
217  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
-
218 }
+

Definition at line 220 of file QuEST_validation.c.

+
220  {
+
221  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
+
222 }

References Complex::imag, and Complex::real.

@@ -957,17 +957,17 @@

-

Definition at line 259 of file QuEST_validation.c.

-
259  {
-
260  int dim = 2;
-
261  int retVal;
-
262  macro_isMatrixUnitary(u, dim, retVal);
-
263  return retVal;
-
264 }
+

Definition at line 263 of file QuEST_validation.c.

+
263  {
+
264  int dim = 2;
+
265  int retVal;
+
266  macro_isMatrixUnitary(u, dim, retVal);
+
267  return retVal;
+
268 }
-

References macro_isMatrixUnitary.

+

References macro_isMatrixUnitary.

-

Referenced by validateOneQubitUnitaryMatrix().

+

Referenced by validateOneQubitUnitaryMatrix().

@@ -987,17 +987,17 @@

-

Definition at line 265 of file QuEST_validation.c.

-
265  {
-
266  int dim = 4;
-
267  int retVal;
-
268  macro_isMatrixUnitary(u, dim, retVal);
-
269  return retVal;
-
270 }
+

Definition at line 269 of file QuEST_validation.c.

+
269  {
+
270  int dim = 4;
+
271  int retVal;
+
272  macro_isMatrixUnitary(u, dim, retVal);
+
273  return retVal;
+
274 }
-

References macro_isMatrixUnitary.

+

References macro_isMatrixUnitary.

-

Referenced by validateTwoQubitUnitaryMatrix().

+

Referenced by validateTwoQubitUnitaryMatrix().

@@ -1017,17 +1017,17 @@

-

Definition at line 271 of file QuEST_validation.c.

-
271  {
-
272  int dim = 1 << u.numQubits;
-
273  int retVal;
-
274  macro_isMatrixUnitary(u, dim, retVal);
-
275  return retVal;
-
276 }
+

Definition at line 275 of file QuEST_validation.c.

+
275  {
+
276  int dim = 1 << u.numQubits;
+
277  int retVal;
+
278  macro_isMatrixUnitary(u, dim, retVal);
+
279  return retVal;
+
280 }
-

References macro_isMatrixUnitary, and ComplexMatrixN::numQubits.

+

References macro_isMatrixUnitary, and ComplexMatrixN::numQubits.

-

Referenced by validateMultiQubitUnitaryMatrix().

+

Referenced by validateMultiQubitUnitaryMatrix().

@@ -1047,14 +1047,14 @@

-

Definition at line 307 of file QuEST_validation.c.

-
307  {
-
308  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
-
309 }
+

Definition at line 311 of file QuEST_validation.c.

+
311  {
+
312  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
+
313 }

References PAULI_I, PAULI_X, PAULI_Y, and PAULI_Z.

-

Referenced by validateHamilFilePauliCode(), and validatePauliCodes().

+

Referenced by validateHamilFilePauliCode(), and validatePauliCodes().

@@ -1090,10 +1090,10 @@

-

Definition at line 220 of file QuEST_validation.c.

-
220  {
-
221  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
-
222 }
+

Definition at line 224 of file QuEST_validation.c.

+
224  {
+
225  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
+
226 }
@@ -1129,14 +1129,14 @@

-

Definition at line 212 of file QuEST_validation.c.

-
212  {
-
213  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
-
214 }
+

Definition at line 216 of file QuEST_validation.c.

+
216  {
+
217  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
+
218 }
-

References errorMessages, and invalidQuESTInputError().

+

References errorMessages, and invalidQuESTInputError().

-

Referenced by validateAmpIndex(), validateBitEncoding(), validateControl(), validateControlState(), validateControlTarget(), validateDensityMatrQureg(), validateDiagonalOp(), validateDiagOpInit(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), validateHamilParams(), validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), validateMatrixInit(), validateMeasurementProb(), validateMultiControls(), validateMultiControlsMultiTargets(), validateMultiControlsTarget(), validateMultiQubitKrausMap(), validateMultiQubitMatrix(), validateMultiQubitMatrixFitsInNode(), validateMultiQubits(), validateMultiQubitUnitaryMatrix(), validateMultiRegBitEncoding(), validateMultiTargets(), validateMultiVarPhaseFuncOverrides(), validateMultiVarPhaseFuncTerms(), validateNormProbs(), validateNumAmps(), validateNumControls(), validateNumElems(), validateNumPauliSumTerms(), validateNumQubitsInDiagOp(), validateNumQubitsInMatrix(), validateNumQubitsInQureg(), validateNumRanks(), validateNumTargets(), validateOneQubitDampingProb(), validateOneQubitDephaseProb(), validateOneQubitDepolProb(), validateOneQubitKrausMap(), validateOneQubitPauliProbs(), validateOneQubitUnitaryMatrix(), validateOutcome(), validatePauliCodes(), validatePhaseFuncName(), validatePhaseFuncOverrides(), validatePhaseFuncTerms(), validateProb(), validateQubitSubregs(), validateSecondQuregStateVec(), validateStateIndex(), validateStateVecQureg(), validateTarget(), validateTrotterParams(), validateTwoQubitDephaseProb(), validateTwoQubitDepolProb(), validateTwoQubitKrausMap(), validateTwoQubitUnitaryMatrix(), validateUniqueTargets(), validateUnitaryComplexPair(), and validateVector().

+

Referenced by validateAmpIndex(), validateBitEncoding(), validateControl(), validateControlState(), validateControlTarget(), validateDensityMatrQureg(), validateDiagonalOp(), validateDiagOpInit(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), validateHamilParams(), validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), validateMatrixInit(), validateMeasurementProb(), validateMultiControls(), validateMultiControlsMultiTargets(), validateMultiControlsTarget(), validateMultiQubitKrausMap(), validateMultiQubitMatrix(), validateMultiQubitMatrixFitsInNode(), validateMultiQubits(), validateMultiQubitUnitaryMatrix(), validateMultiRegBitEncoding(), validateMultiTargets(), validateMultiVarPhaseFuncOverrides(), validateMultiVarPhaseFuncTerms(), validateNormProbs(), validateNumAmps(), validateNumControls(), validateNumElems(), validateNumPauliSumTerms(), validateNumQubitsInDiagOp(), validateNumQubitsInMatrix(), validateNumQubitsInQureg(), validateNumRanks(), validateNumTargets(), validateOneQubitDampingProb(), validateOneQubitDephaseProb(), validateOneQubitDepolProb(), validateOneQubitKrausMap(), validateOneQubitPauliProbs(), validateOneQubitUnitaryMatrix(), validateOutcome(), validatePauliCodes(), validatePhaseFuncName(), validatePhaseFuncOverrides(), validatePhaseFuncTerms(), validateProb(), validateQubitSubregs(), validateSecondQuregStateVec(), validateStateIndex(), validateStateVecQureg(), validateTarget(), validateTrotterParams(), validateTwoQubitDephaseProb(), validateTwoQubitDepolProb(), validateTwoQubitKrausMap(), validateTwoQubitUnitaryMatrix(), validateUniqueTargets(), validateUnitaryComplexPair(), and validateVector().

@@ -1172,15 +1172,15 @@

-

Definition at line 378 of file QuEST_validation.c.

-
378  {
-
379  long long int indMax = 1LL << qureg.numQubitsRepresented;
-
380  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
-
381 }
+

Definition at line 382 of file QuEST_validation.c.

+
382  {
+
383  long long int indMax = 1LL << qureg.numQubitsRepresented;
+
384  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
+
385 }
-

References E_INVALID_AMP_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_AMP_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by getAmp(), getDensityAmp(), getImagAmp(), getProbAmp(), getRealAmp(), and validateNumAmps().

+

Referenced by getAmp(), getDensityAmp(), getImagAmp(), getProbAmp(), getRealAmp(), and validateNumAmps().

@@ -1216,20 +1216,20 @@

-

Definition at line 961 of file QuEST_validation.c.

-
961  {
-
962  QuESTAssert(
-
963  encoding == UNSIGNED ||
-
964  encoding == TWOS_COMPLEMENT,
-
965  E_INVALID_BIT_ENCODING, caller);
-
966 
-
967  if (encoding == TWOS_COMPLEMENT)
-
968  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
-
969 }
+

Definition at line 966 of file QuEST_validation.c.

+
966  {
+
967  QuESTAssert(
+
968  encoding == UNSIGNED ||
+
969  encoding == TWOS_COMPLEMENT,
+
970  E_INVALID_BIT_ENCODING, caller);
+
971 
+
972  if (encoding == TWOS_COMPLEMENT)
+
973  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
+
974 }
-

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -1265,14 +1265,14 @@

-

Definition at line 400 of file QuEST_validation.c.

-
400  {
-
401  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
-
402 }
+

Definition at line 404 of file QuEST_validation.c.

+
404  {
+
405  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
+
406 }
-

References E_INVALID_CONTROL_QUBIT, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_CONTROL_QUBIT, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by validateControlTarget(), and validateMultiControls().

+

Referenced by validateControlTarget(), and validateMultiControls().

@@ -1308,15 +1308,15 @@

-

Definition at line 464 of file QuEST_validation.c.

-
464  {
-
465  for (int i=0; i < numControlQubits; i++)
-
466  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
-
467 }
+

Definition at line 468 of file QuEST_validation.c.

+
468  {
+
469  for (int i=0; i < numControlQubits; i++)
+
470  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
+
471 }
-

References E_INVALID_CONTROLS_BIT_STATE, and QuESTAssert().

+

References E_INVALID_CONTROLS_BIT_STATE, and QuESTAssert().

-

Referenced by multiStateControlledUnitary().

+

Referenced by multiStateControlledUnitary().

@@ -1358,16 +1358,16 @@

-

Definition at line 404 of file QuEST_validation.c.

- @@ -1397,14 +1397,14 @@

-

Definition at line 515 of file QuEST_validation.c.

- @@ -1440,15 +1440,15 @@

-

Definition at line 709 of file QuEST_validation.c.

- @@ -1478,14 +1478,14 @@

-

Definition at line 705 of file QuEST_validation.c.

- @@ -1521,19 +1521,19 @@

-

Definition at line 714 of file QuEST_validation.c.

- @@ -1569,40 +1569,40 @@

-

Definition at line 723 of file QuEST_validation.c.

-
723  {
-
724  // hamil itself already validated as general Pauli Hamiltonian
-
725 
-
726  // destroy hamil before raising exceptions if validation fails
-
727  int isValid;
-
728 
-
729  // mustn't be more elements than can fit in the type
-
730  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
731  isValid = hamil.numQubits <= maxQubits;
-
732  if (!isValid)
-
733  destroyPauliHamil(hamil);
-
734  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
-
735 
-
736  // must be at least one amplitude per node
-
737  long unsigned int numElems = (1UL<<hamil.numQubits);
-
738  isValid = numElems >= numRanks;
-
739  if (!isValid)
-
740  destroyPauliHamil(hamil);
-
741  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
742 
-
743  // must contain only I and Z
-
744  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
-
745  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
-
746  if (!isValid)
-
747  destroyPauliHamil(hamil);
-
748 
-
749  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
-
750  }
-
751 }
+

Definition at line 727 of file QuEST_validation.c.

+
727  {
+
728  // hamil itself already validated as general Pauli Hamiltonian
+
729 
+
730  // destroy hamil before raising exceptions if validation fails
+
731  int isValid;
+
732 
+
733  // mustn't be more elements than can fit in the type
+
734  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
735  isValid = hamil.numQubits <= maxQubits;
+
736  if (!isValid)
+
737  destroyPauliHamil(hamil);
+
738  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
+
739 
+
740  // must be at least one amplitude per node
+
741  long unsigned int numElems = (1UL<<hamil.numQubits);
+
742  isValid = numElems >= numRanks;
+
743  if (!isValid)
+
744  destroyPauliHamil(hamil);
+
745  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
+
746 
+
747  // must contain only I and Z
+
748  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
+
749  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
+
750  if (!isValid)
+
751  destroyPauliHamil(hamil);
+
752 
+
753  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
+
754  }
+
755 }
-

References calcLog2(), destroyPauliHamil(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_NUM_AMPS_EXCEED_TYPE, E_PAULI_HAMIL_NOT_DIAGONAL, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_Z, PauliHamil::pauliCodes, and QuESTAssert().

+

References calcLog2(), destroyPauliHamil(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_NUM_AMPS_EXCEED_TYPE, E_PAULI_HAMIL_NOT_DIAGONAL, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_Z, PauliHamil::pauliCodes, and QuESTAssert().

-

Referenced by createDiagonalOpFromPauliHamilFile().

+

Referenced by createDiagonalOpFromPauliHamilFile().

@@ -1638,18 +1638,18 @@

-

Definition at line 539 of file QuEST_validation.c.

-
539  {
-
540  if (!opened) {
-
541 
- - -
544  }
-
545 }
+

Definition at line 543 of file QuEST_validation.c.

+
543  {
+
544  if (!opened) {
+
545 
+ + +
548  }
+
549 }
-

References E_CANNOT_OPEN_FILE, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References E_CANNOT_OPEN_FILE, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile(), initStateFromSingleFile(), and writeRecordedQASMToFile().

+

Referenced by createPauliHamilFromFile(), initStateFromSingleFile(), and writeRecordedQASMToFile().

@@ -1697,20 +1697,20 @@

-

Definition at line 669 of file QuEST_validation.c.

-
669  {
-
670  if (!parsed) {
- -
672  fclose(file);
-
673 
- - -
676  }
-
677 }
+

Definition at line 673 of file QuEST_validation.c.

+
673  {
+
674  if (!parsed) {
+ +
676  fclose(file);
+
677 
+ + +
680  }
+
681 }
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -1758,19 +1758,19 @@

-

Definition at line 660 of file QuEST_validation.c.

-
660  {
-
661  if (!(numQubits > 0 && numTerms > 0)) {
-
662  fclose(file);
-
663 
- - -
666  }
-
667 }
+

Definition at line 664 of file QuEST_validation.c.

+
664  {
+
665  if (!(numQubits > 0 && numTerms > 0)) {
+
666  fclose(file);
+
667 
+ + +
670  }
+
671 }
-

References E_INVALID_PAULI_HAMIL_FILE_PARAMS, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References E_INVALID_PAULI_HAMIL_FILE_PARAMS, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -1818,20 +1818,20 @@

-

Definition at line 689 of file QuEST_validation.c.

-
689  {
-
690  if (!isValidPauliCode(code)) {
- -
692  fclose(file);
-
693 
- - -
696  }
-
697 }
+

Definition at line 693 of file QuEST_validation.c.

+
693  {
+
694  if (!isValidPauliCode(code)) {
+ +
696  fclose(file);
+
697 
+ + +
700  }
+
701 }
-

References destroyPauliHamil(), E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, errMsgBuffer, errorMessages, invalidQuESTInputError(), and isValidPauliCode().

+

References destroyPauliHamil(), E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, errMsgBuffer, errorMessages, invalidQuESTInputError(), and isValidPauliCode().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -1879,20 +1879,20 @@

-

Definition at line 679 of file QuEST_validation.c.

-
679  {
-
680  if (!parsed) {
- -
682  fclose(file);
-
683 
- - -
686  }
-
687 }
+

Definition at line 683 of file QuEST_validation.c.

+
683  {
+
684  if (!parsed) {
+ +
686  fclose(file);
+
687 
+ + +
690  }
+
691 }
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -1928,14 +1928,14 @@

-

Definition at line 647 of file QuEST_validation.c.

-
647  {
-
648  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
-
649 }
+

Definition at line 651 of file QuEST_validation.c.

+
651  {
+
652  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
+
653 }
-

References E_INVALID_PAULI_HAMIL_PARAMS, and QuESTAssert().

+

References E_INVALID_PAULI_HAMIL_PARAMS, and QuESTAssert().

-

Referenced by createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), and validatePauliHamil().

+

Referenced by createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), and validatePauliHamil().

@@ -1971,14 +1971,14 @@

-

Definition at line 527 of file QuEST_validation.c.

- @@ -2014,14 +2014,14 @@

-

Definition at line 656 of file QuEST_validation.c.

- @@ -2057,14 +2057,14 @@

-

Definition at line 531 of file QuEST_validation.c.

- @@ -2094,20 +2094,20 @@

-

Definition at line 482 of file QuEST_validation.c.

-
482  {
-
483 
-
484  /* note that for (most) compilers which don't automatically initialise
-
485  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
-
486  * succeeded. It can not be used to differentiate whether a user actually attempted
-
487  * to initialise or create their ComplexMatrixN instance.
-
488  */
-
489  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
-
490 }
+

Definition at line 486 of file QuEST_validation.c.

+
486  {
+
487 
+
488  /* note that for (most) compilers which don't automatically initialise
+
489  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
+
490  * succeeded. It can not be used to differentiate whether a user actually attempted
+
491  * to initialise or create their ComplexMatrixN instance.
+
492  */
+
493  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
+
494 }
-

References E_COMPLEX_MATRIX_NOT_INIT, ComplexMatrixN::imag, QuESTAssert(), and ComplexMatrixN::real.

+

References E_COMPLEX_MATRIX_NOT_INIT, ComplexMatrixN::imag, QuESTAssert(), and ComplexMatrixN::real.

-

Referenced by createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), validateMultiQubitKrausMap(), and validateMultiQubitMatrix().

+

Referenced by createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), validateMultiQubitKrausMap(), and validateMultiQubitMatrix().

@@ -2137,14 +2137,14 @@

-

Definition at line 523 of file QuEST_validation.c.

-
523  {
-
524  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
-
525 }
+

Definition at line 527 of file QuEST_validation.c.

+
527  {
+
528  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
+
529 }
-

References E_COLLAPSE_STATE_ZERO_PROB, and QuESTAssert().

+

References E_COLLAPSE_STATE_ZERO_PROB, and QuESTAssert().

-

Referenced by collapseToOutcome().

+

Referenced by collapseToOutcome().

@@ -2186,18 +2186,18 @@

-

Definition at line 432 of file QuEST_validation.c.

-
432  {
-
433  validateNumControls(qureg, numControlQubits, caller);
-
434  for (int i=0; i < numControlQubits; i++)
-
435  validateControl(qureg, controlQubits[i], caller);
-
436 
-
437  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
-
438 }
+

Definition at line 436 of file QuEST_validation.c.

+
436  {
+
437  validateNumControls(qureg, numControlQubits, caller);
+
438  for (int i=0; i < numControlQubits; i++)
+
439  validateControl(qureg, controlQubits[i], caller);
+
440 
+
441  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
+
442 }
-

References areUniqueQubits(), E_CONTROLS_NOT_UNIQUE, QuESTAssert(), validateControl(), and validateNumControls().

+

References areUniqueQubits(), E_CONTROLS_NOT_UNIQUE, QuESTAssert(), validateControl(), and validateNumControls().

-

Referenced by validateMultiControlsMultiTargets(), and validateMultiControlsTarget().

+

Referenced by validateMultiControlsMultiTargets(), and validateMultiControlsTarget().

@@ -2251,19 +2251,19 @@

-

Definition at line 455 of file QuEST_validation.c.

-
455  {
-
456  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
457  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
-
458  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
-
459  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
-
460  int overlap = ctrlMask & targMask;
-
461  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
-
462 }
+

Definition at line 459 of file QuEST_validation.c.

+
459  {
+
460  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
+
461  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
+
462  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
+
463  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
+
464  int overlap = ctrlMask & targMask;
+
465  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
+
466 }
-

References E_CONTROL_TARGET_COLLISION, getQubitBitMask(), QuESTAssert(), validateMultiControls(), and validateMultiTargets().

+

References E_CONTROL_TARGET_COLLISION, getQubitBitMask(), QuESTAssert(), validateMultiControls(), and validateMultiTargets().

-

Referenced by applyMultiControlledMatrixN(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), and multiControlledTwoQubitUnitary().

+

Referenced by applyMultiControlledMatrixN(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), and multiControlledTwoQubitUnitary().

@@ -2311,17 +2311,17 @@

-

Definition at line 448 of file QuEST_validation.c.

-
448  {
-
449  validateTarget(qureg, targetQubit, caller);
-
450  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
451  for (int i=0; i < numControlQubits; i++)
-
452  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
-
453 }
+

Definition at line 452 of file QuEST_validation.c.

+
452  {
+
453  validateTarget(qureg, targetQubit, caller);
+
454  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
+
455  for (int i=0; i < numControlQubits; i++)
+
456  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
+
457 }
-

References E_TARGET_IN_CONTROLS, QuESTAssert(), validateMultiControls(), and validateTarget().

+

References E_TARGET_IN_CONTROLS, QuESTAssert(), validateMultiControls(), and validateTarget().

-

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

+

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

@@ -2369,27 +2369,27 @@

-

Definition at line 630 of file QuEST_validation.c.

-
630  {
-
631  int opNumQubits = numTargs;
-
632  int superOpNumQubits = 2*opNumQubits;
-
633  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
634  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
-
635 
-
636  for (int n=0; n<numOps; n++) {
-
637  validateMatrixInit(ops[n], __func__);
-
638  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
-
639  }
-
640 
-
641  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
642 
-
643  int isPos = isCompletelyPositiveMapN(ops, numOps);
-
644  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
645 }
+

Definition at line 634 of file QuEST_validation.c.

+
634  {
+
635  int opNumQubits = numTargs;
+
636  int superOpNumQubits = 2*opNumQubits;
+
637  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
638  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
+
639 
+
640  for (int n=0; n<numOps; n++) {
+
641  validateMatrixInit(ops[n], __func__);
+
642  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
+
643  }
+
644 
+
645  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
646 
+
647  int isPos = isCompletelyPositiveMapN(ops, numOps);
+
648  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
649 }
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, isCompletelyPositiveMapN(), QuESTAssert(), validateMatrixInit(), and validateMultiQubitMatrixFitsInNode().

+

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, isCompletelyPositiveMapN(), QuESTAssert(), validateMatrixInit(), and validateMultiQubitMatrixFitsInNode().

-

Referenced by mixMultiQubitKrausMap().

+

Referenced by mixMultiQubitKrausMap().

@@ -2431,16 +2431,16 @@

-

Definition at line 492 of file QuEST_validation.c.

- @@ -2476,14 +2476,14 @@

-

Definition at line 469 of file QuEST_validation.c.

- @@ -2525,18 +2525,18 @@

-

Definition at line 440 of file QuEST_validation.c.

-
440  {
-
441  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
-
442  for (int i=0; i < numQubits; i++)
-
443  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
444 
-
445  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
-
446 }
+

Definition at line 444 of file QuEST_validation.c.

+
444  {
+
445  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
446  for (int i=0; i < numQubits; i++)
+
447  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
+
448 
+
449  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
+
450 }
-

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, Qureg::numQubitsRepresented, and QuESTAssert().

+

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), multiControlledPhaseFlip(), and multiControlledPhaseShift().

+

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), multiControlledPhaseFlip(), and multiControlledPhaseShift().

@@ -2578,15 +2578,15 @@

-

Definition at line 498 of file QuEST_validation.c.

- @@ -2628,21 +2628,21 @@

-

Definition at line 971 of file QuEST_validation.c.

-
971  {
-
972  QuESTAssert(
-
973  encoding == UNSIGNED ||
-
974  encoding == TWOS_COMPLEMENT,
-
975  E_INVALID_BIT_ENCODING, caller);
-
976 
-
977  if (encoding == TWOS_COMPLEMENT)
-
978  for (int r=0; r<numRegs; r++)
-
979  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
-
980 }
+

Definition at line 976 of file QuEST_validation.c.

+
976  {
+
977  QuESTAssert(
+
978  encoding == UNSIGNED ||
+
979  encoding == TWOS_COMPLEMENT,
+
980  E_INVALID_BIT_ENCODING, caller);
+
981 
+
982  if (encoding == TWOS_COMPLEMENT)
+
983  for (int r=0; r<numRegs; r++)
+
984  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
+
985 }
-

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -2684,18 +2684,18 @@

-

Definition at line 424 of file QuEST_validation.c.

-
424  {
-
425  validateNumTargets(qureg, numTargetQubits, caller);
-
426  for (int i=0; i < numTargetQubits; i++)
-
427  validateTarget(qureg, targetQubits[i], caller);
-
428 
-
429  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
-
430 }
+

Definition at line 428 of file QuEST_validation.c.

+
428  {
+
429  validateNumTargets(qureg, numTargetQubits, caller);
+
430  for (int i=0; i < numTargetQubits; i++)
+
431  validateTarget(qureg, targetQubits[i], caller);
+
432 
+
433  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
+
434 }
-

References areUniqueQubits(), E_TARGETS_NOT_UNIQUE, QuESTAssert(), validateNumTargets(), and validateTarget().

+

References areUniqueQubits(), E_TARGETS_NOT_UNIQUE, QuESTAssert(), validateNumTargets(), and validateTarget().

-

Referenced by applyMatrix4(), applyMatrixN(), applyQFT(), calcExpecPauliProd(), calcProbOfAllOutcomes(), mixMultiQubitKrausMap(), mixTwoQubitKrausMap(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), twoQubitUnitary(), and validateMultiControlsMultiTargets().

+

Referenced by applyMatrix4(), applyMatrixN(), applyQFT(), calcExpecPauliProd(), calcProbOfAllOutcomes(), mixMultiQubitKrausMap(), mixTwoQubitKrausMap(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), twoQubitUnitary(), and validateMultiControlsMultiTargets().

@@ -2749,37 +2749,37 @@

-

Definition at line 881 of file QuEST_validation.c.

-
881  {
-
882  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
883 
-
884  if (encoding == UNSIGNED) {
-
885  int i=0;
-
886  for (int v=0; v<numOverrides; v++) {
-
887  for (int r=0; r<numRegs; r++) {
-
888  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
-
889  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
-
890  i++;
-
891  }
-
892  }
-
893  }
-
894  else if (encoding == TWOS_COMPLEMENT) {
-
895  int i=0;
-
896  for (int v=0; v<numOverrides; v++) {
-
897  for (int r=0; r<numRegs; r++) {
-
898  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
-
899  long long int minInd = - (1LL << numValQubits);
-
900  long long int maxInd = (1LL << numValQubits) - 1;
-
901  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
-
902  i++;
-
903  }
-
904  }
-
905  }
-
906 }
+

Definition at line 886 of file QuEST_validation.c.

+
886  {
+
887  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
888 
+
889  if (encoding == UNSIGNED) {
+
890  int i=0;
+
891  for (int v=0; v<numOverrides; v++) {
+
892  for (int r=0; r<numRegs; r++) {
+
893  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
+
894  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
+
895  i++;
+
896  }
+
897  }
+
898  }
+
899  else if (encoding == TWOS_COMPLEMENT) {
+
900  int i=0;
+
901  for (int v=0; v<numOverrides; v++) {
+
902  for (int r=0; r<numRegs; r++) {
+
903  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
+
904  long long int minInd = - (1LL << numValQubits);
+
905  long long int maxInd = (1LL << numValQubits) - 1;
+
906  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
+
907  i++;
+
908  }
+
909  }
+
910  }
+
911 }
-

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFuncOverrides(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFuncOverrides(), and applyParamNamedPhaseFuncOverrides().

@@ -2833,35 +2833,35 @@

-

Definition at line 831 of file QuEST_validation.c.

-
831  {
- -
833  for (int r=0; r<numRegs; r++)
-
834  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
-
835 
-
836  int numTotalTerms = 0;
-
837  for (int r=0; r<numRegs; r++)
-
838  numTotalTerms += numTermsPerReg[r];
-
839 
-
840  int hasFractionExpo = 0;
-
841  int hasNegativeExpo = 0;
-
842  for (int t=0; t<numTotalTerms; t++) {
-
843  // this is only true if exponent is precisely an integer, else pow() will NaN
-
844  if (floor(exponents[t]) != exponents[t])
-
845  hasFractionExpo = 1;
-
846  if (exponents[t] < 0)
-
847  hasNegativeExpo = 1;
-
848  }
-
849 
-
850  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
-
851 
-
852  if (encoding == TWOS_COMPLEMENT)
-
853  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
-
854 }
+

Definition at line 836 of file QuEST_validation.c.

+
836  {
+ +
838  for (int r=0; r<numRegs; r++)
+
839  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
+
840 
+
841  int numTotalTerms = 0;
+
842  for (int r=0; r<numRegs; r++)
+
843  numTotalTerms += numTermsPerReg[r];
+
844 
+
845  int hasFractionExpo = 0;
+
846  int hasNegativeExpo = 0;
+
847  for (int t=0; t<numTotalTerms; t++) {
+
848  // this is only true if exponent is precisely an integer, else pow() will NaN
+
849  if (floor(exponents[t]) != exponents[t])
+
850  hasFractionExpo = 1;
+
851  if (exponents[t] < 0)
+
852  hasNegativeExpo = 1;
+
853  }
+
854 
+
855  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
+
856 
+
857  if (encoding == TWOS_COMPLEMENT)
+
858  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
+
859 }
-

References E_FRACTIONAL_EXPONENT_MULTI_VAR, E_INVALID_NUM_PHASE_FUNC_TERMS, E_INVALID_NUM_SUBREGISTERS, E_NEGATIVE_EXPONENT_MULTI_VAR, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, QuESTAssert(), and TWOS_COMPLEMENT.

+

References E_FRACTIONAL_EXPONENT_MULTI_VAR, E_INVALID_NUM_PHASE_FUNC_TERMS, E_INVALID_NUM_SUBREGISTERS, E_NEGATIVE_EXPONENT_MULTI_VAR, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, QuESTAssert(), and TWOS_COMPLEMENT.

-

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

@@ -2897,16 +2897,16 @@

-

Definition at line 551 of file QuEST_validation.c.

-
551  {
-
552  validateProb(prob1, caller);
-
553  validateProb(prob2, caller);
-
554 
-
555  qreal sum = prob1 + prob2;
-
556  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
-
557 }
+

Definition at line 555 of file QuEST_validation.c.

+
555  {
+
556  validateProb(prob1, caller);
+
557  validateProb(prob2, caller);
+
558 
+
559  qreal sum = prob1 + prob2;
+
560  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
+
561 }
-

References E_UNNORM_PROBS, qreal, QuESTAssert(), and validateProb().

+

References E_UNNORM_PROBS, qreal, QuESTAssert(), and validateProb().

@@ -2948,16 +2948,16 @@

-

Definition at line 383 of file QuEST_validation.c.

-
383  {
-
384  validateAmpIndex(qureg, startInd, caller);
-
385  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
-
386  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
-
387 }
+

Definition at line 387 of file QuEST_validation.c.

+
387  {
+
388  validateAmpIndex(qureg, startInd, caller);
+
389  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
+
390  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
+
391 }
-

References E_INVALID_NUM_AMPS, E_INVALID_OFFSET_NUM_AMPS_QUREG, Qureg::numAmpsTotal, QuESTAssert(), and validateAmpIndex().

+

References E_INVALID_NUM_AMPS, E_INVALID_OFFSET_NUM_AMPS_QUREG, Qureg::numAmpsTotal, QuESTAssert(), and validateAmpIndex().

-

Referenced by setAmps().

+

Referenced by setAmps().

@@ -2993,14 +2993,14 @@

-

Definition at line 420 of file QuEST_validation.c.

-
420  {
-
421  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
-
422 }
+

Definition at line 424 of file QuEST_validation.c.

+
424  {
+
425  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
+
426 }
-

References E_INVALID_NUM_CONTROLS, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_NUM_CONTROLS, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by validateMultiControls().

+

Referenced by validateMultiControls().

@@ -3042,17 +3042,17 @@

-

Definition at line 389 of file QuEST_validation.c.

-
389  {
-
390  long long int indMax = 1LL << op.numQubits;
-
391  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
-
392  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
-
393  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
-
394 }
+

Definition at line 393 of file QuEST_validation.c.

+
393  {
+
394  long long int indMax = 1LL << op.numQubits;
+
395  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
+
396  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
+
397  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
+
398 }
-

References E_INVALID_ELEM_INDEX, E_INVALID_NUM_ELEMS, E_INVALID_OFFSET_NUM_ELEMS_DIAG, DiagonalOp::numQubits, and QuESTAssert().

+

References E_INVALID_ELEM_INDEX, E_INVALID_NUM_ELEMS, E_INVALID_OFFSET_NUM_ELEMS_DIAG, DiagonalOp::numQubits, and QuESTAssert().

-

Referenced by setDiagonalOpElems().

+

Referenced by setDiagonalOpElems().

@@ -3082,14 +3082,14 @@

-

Definition at line 602 of file QuEST_validation.c.

-
602  {
-
603  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
-
604 }
+

Definition at line 606 of file QuEST_validation.c.

+
606  {
+
607  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
+
608 }
-

References E_INVALID_NUM_SUM_TERMS, and QuESTAssert().

+

References E_INVALID_NUM_SUM_TERMS, and QuESTAssert().

-

Referenced by applyPauliSum(), and calcExpecPauliSum().

+

Referenced by applyPauliSum(), and calcExpecPauliSum().

@@ -3125,22 +3125,22 @@

-

Definition at line 361 of file QuEST_validation.c.

-
361  {
-
362  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
363 
-
364  // mustn't be more amplitudes than can fit in the type
-
365  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
366  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+

Definition at line 365 of file QuEST_validation.c.

+
365  {
+
366  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
367 
-
368  // must be at least one amplitude per node
-
369  long unsigned int numAmps = (1UL<<numQubits);
-
370  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
371 }
+
368  // mustn't be more amplitudes than can fit in the type
+
369  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
370  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
371 
+
372  // must be at least one amplitude per node
+
373  long unsigned int numAmps = (1UL<<numQubits);
+
374  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
+
375 }
-

References calcLog2(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

+

References calcLog2(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

-

Referenced by createDiagonalOp().

+

Referenced by createDiagonalOp().

@@ -3170,14 +3170,14 @@

-

Definition at line 357 of file QuEST_validation.c.

-
357  {
-
358  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
-
359 }
+

Definition at line 361 of file QuEST_validation.c.

+
361  {
+
362  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
+
363 }
-

References E_INVALID_NUM_QUBITS, and QuESTAssert().

+

References E_INVALID_NUM_QUBITS, and QuESTAssert().

-

Referenced by createComplexMatrixN().

+

Referenced by createComplexMatrixN().

@@ -3213,20 +3213,20 @@

-

Definition at line 345 of file QuEST_validation.c.

-
345  {
-
346  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
347 
-
348  // mustn't be more amplitudes than can fit in the type
-
349  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
350  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+

Definition at line 349 of file QuEST_validation.c.

+
349  {
+
350  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
351 
-
352  // must be at least one amplitude per node
-
353  long unsigned int numAmps = (1UL<<numQubits);
-
354  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
-
355 }
+
352  // mustn't be more amplitudes than can fit in the type
+
353  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
354  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
355 
+
356  // must be at least one amplitude per node
+
357  long unsigned int numAmps = (1UL<<numQubits);
+
358  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
+
359 }
-

References calcLog2(), E_DISTRIB_QUREG_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

+

References calcLog2(), E_DISTRIB_QUREG_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

Referenced by createDensityQureg(), and createQureg().

@@ -3258,22 +3258,22 @@

-

Definition at line 331 of file QuEST_validation.c.

-
331  {
-
332 
-
333  /* silly but robust way to determine if numRanks is a power of 2,
-
334  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
-
335  * system / precsision dependent
-
336  */
-
337  int isValid = 0;
-
338  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
-
339  if (exp2 == numRanks)
-
340  isValid = 1;
-
341 
-
342  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
-
343 }
+

Definition at line 335 of file QuEST_validation.c.

+
335  {
+
336 
+
337  /* silly but robust way to determine if numRanks is a power of 2,
+
338  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
+
339  * system / precsision dependent
+
340  */
+
341  int isValid = 0;
+
342  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
+
343  if (exp2 == numRanks)
+
344  isValid = 1;
+
345 
+
346  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
+
347 }
-

References E_INVALID_NUM_RANKS, and QuESTAssert().

+

References E_INVALID_NUM_RANKS, and QuESTAssert().

Referenced by createQuESTEnv().

@@ -3311,14 +3311,14 @@

-

Definition at line 416 of file QuEST_validation.c.

-
416  {
-
417  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
-
418 }
+

Definition at line 420 of file QuEST_validation.c.

+
420  {
+
421  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
+
422 }
-

References E_INVALID_NUM_TARGETS, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_NUM_TARGETS, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by validateMultiTargets().

+

Referenced by validateMultiTargets().

@@ -3348,15 +3348,15 @@

-

Definition at line 574 of file QuEST_validation.c.

-
574  {
-
575  validateProb(prob, caller);
-
576  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
577 }
+

Definition at line 578 of file QuEST_validation.c.

+
578  {
+
579  validateProb(prob, caller);
+
580  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
+
581 }
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixDamping().

+

Referenced by mixDamping().

@@ -3386,15 +3386,15 @@

-

Definition at line 559 of file QuEST_validation.c.

-
559  {
-
560  validateProb(prob, caller);
-
561  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
-
562 }
+

Definition at line 563 of file QuEST_validation.c.

+
563  {
+
564  validateProb(prob, caller);
+
565  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
+
566 }
-

References E_INVALID_ONE_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixDephasing().

+

Referenced by mixDephasing().

@@ -3424,15 +3424,15 @@

-

Definition at line 569 of file QuEST_validation.c.

-
569  {
-
570  validateProb(prob, caller);
-
571  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
572 }
+

Definition at line 573 of file QuEST_validation.c.

+
573  {
+
574  validateProb(prob, caller);
+
575  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
+
576 }
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixDepolarising().

+

Referenced by mixDepolarising().

@@ -3474,22 +3474,22 @@

-

Definition at line 606 of file QuEST_validation.c.

-
606  {
-
607  int opNumQubits = 1;
-
608  int superOpNumQubits = 2*opNumQubits;
-
609  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
610  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
-
611 
-
612  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
613 
-
614  int isPos = isCompletelyPositiveMap2(ops, numOps);
-
615  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
616 }
+

Definition at line 610 of file QuEST_validation.c.

+
610  {
+
611  int opNumQubits = 1;
+
612  int superOpNumQubits = 2*opNumQubits;
+
613  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
614  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
+
615 
+
616  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
617 
+
618  int isPos = isCompletelyPositiveMap2(ops, numOps);
+
619  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
620 }
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, isCompletelyPositiveMap2(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

+

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, isCompletelyPositiveMap2(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

-

Referenced by mixKrausMap().

+

Referenced by mixKrausMap().

@@ -3531,21 +3531,21 @@

-

Definition at line 584 of file QuEST_validation.c.

-
584  {
-
585  validateProb(probX, caller);
-
586  validateProb(probY, caller);
-
587  validateProb(probZ, caller);
-
588 
-
589  qreal probNoError = 1 - probX - probY - probZ;
-
590  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
591  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
592  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
593 }
+

Definition at line 588 of file QuEST_validation.c.

+
588  {
+
589  validateProb(probX, caller);
+
590  validateProb(probY, caller);
+
591  validateProb(probZ, caller);
+
592 
+
593  qreal probNoError = 1 - probX - probY - probZ;
+
594  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
595  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
596  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
597 }
-

References E_INVALID_ONE_QUBIT_PAULI_PROBS, qreal, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_PAULI_PROBS, qreal, QuESTAssert(), and validateProb().

-

Referenced by mixPauli().

+

Referenced by mixPauli().

@@ -3575,14 +3575,14 @@

-

Definition at line 473 of file QuEST_validation.c.

- @@ -3612,14 +3612,14 @@

-

Definition at line 519 of file QuEST_validation.c.

-
519  {
-
520  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
-
521 }
+

Definition at line 523 of file QuEST_validation.c.

+
523  {
+
524  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
+
525 }
-

References E_INVALID_QUBIT_OUTCOME, and QuESTAssert().

+

References E_INVALID_QUBIT_OUTCOME, and QuESTAssert().

-

Referenced by calcProbOfOutcome(), collapseToOutcome(), and initStateOfSingleQubit().

+

Referenced by applyProjector(), calcProbOfOutcome(), collapseToOutcome(), and initStateOfSingleQubit().

@@ -3655,17 +3655,17 @@

-

Definition at line 595 of file QuEST_validation.c.

-
595  {
-
596  for (int i=0; i < numPauliCodes; i++) {
-
597  enum pauliOpType code = pauliCodes[i];
- -
599  }
-
600 }
+

Definition at line 599 of file QuEST_validation.c.

+
599  {
+
600  for (int i=0; i < numPauliCodes; i++) {
+
601  enum pauliOpType code = pauliCodes[i];
+ +
603  }
+
604 }
-

References E_INVALID_PAULI_CODE, isValidPauliCode(), and QuESTAssert().

+

References E_INVALID_PAULI_CODE, isValidPauliCode(), and QuESTAssert().

-

Referenced by applyPauliSum(), calcExpecPauliProd(), calcExpecPauliSum(), initPauliHamil(), multiControlledMultiRotatePauli(), multiRotatePauli(), and validatePauliHamil().

+

Referenced by applyPauliSum(), calcExpecPauliProd(), calcExpecPauliSum(), initPauliHamil(), multiControlledMultiRotatePauli(), multiRotatePauli(), and validatePauliHamil().

@@ -3695,15 +3695,15 @@

-

Definition at line 651 of file QuEST_validation.c.

- @@ -3745,63 +3745,63 @@

-

Definition at line 908 of file QuEST_validation.c.

-
908  {
-
909 
-
910  QuESTAssert(
-
911  funcCode == NORM ||
-
912  funcCode == INVERSE_NORM ||
-
913  funcCode == SCALED_NORM ||
-
914  funcCode == SCALED_INVERSE_NORM ||
-
915  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
-
916  funcCode == PRODUCT ||
-
917  funcCode == INVERSE_PRODUCT ||
-
918  funcCode == SCALED_PRODUCT ||
-
919  funcCode == SCALED_INVERSE_PRODUCT ||
-
920  funcCode == DISTANCE ||
-
921  funcCode == INVERSE_DISTANCE ||
-
922  funcCode == SCALED_DISTANCE ||
-
923  funcCode == SCALED_INVERSE_DISTANCE ||
- -
925  E_INVALID_PHASE_FUNC_NAME, caller);
-
926 
-
927  if (funcCode == NORM ||
-
928  funcCode == PRODUCT ||
-
929  funcCode == DISTANCE)
-
930  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
931 
-
932  if (funcCode == INVERSE_NORM ||
-
933  funcCode == INVERSE_PRODUCT ||
-
934  funcCode == INVERSE_DISTANCE)
-
935  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
936 
-
937  if (funcCode == SCALED_NORM ||
-
938  funcCode == SCALED_PRODUCT ||
-
939  funcCode == SCALED_DISTANCE)
+

Definition at line 913 of file QuEST_validation.c.

+
913  {
+
914 
+
915  QuESTAssert(
+
916  funcCode == NORM ||
+
917  funcCode == INVERSE_NORM ||
+
918  funcCode == SCALED_NORM ||
+
919  funcCode == SCALED_INVERSE_NORM ||
+
920  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
+
921  funcCode == PRODUCT ||
+
922  funcCode == INVERSE_PRODUCT ||
+
923  funcCode == SCALED_PRODUCT ||
+
924  funcCode == SCALED_INVERSE_PRODUCT ||
+
925  funcCode == DISTANCE ||
+
926  funcCode == INVERSE_DISTANCE ||
+
927  funcCode == SCALED_DISTANCE ||
+
928  funcCode == SCALED_INVERSE_DISTANCE ||
+ +
930  E_INVALID_PHASE_FUNC_NAME, caller);
+
931 
+
932  if (funcCode == NORM ||
+
933  funcCode == PRODUCT ||
+
934  funcCode == DISTANCE)
+
935  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
936 
+
937  if (funcCode == INVERSE_NORM ||
+
938  funcCode == INVERSE_PRODUCT ||
+
939  funcCode == INVERSE_DISTANCE)
940  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
941 
-
942  if (funcCode == SCALED_INVERSE_NORM ||
-
943  funcCode == SCALED_INVERSE_PRODUCT ||
-
944  funcCode == SCALED_INVERSE_DISTANCE)
-
945  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
946 
-
947  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
-
948  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
949 
-
950  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
-
951  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
952 
-
953  if (funcCode == DISTANCE ||
-
954  funcCode == INVERSE_DISTANCE ||
-
955  funcCode == SCALED_DISTANCE ||
-
956  funcCode == SCALED_INVERSE_DISTANCE ||
- -
958  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
-
959 }
+
942  if (funcCode == SCALED_NORM ||
+
943  funcCode == SCALED_PRODUCT ||
+
944  funcCode == SCALED_DISTANCE)
+
945  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
946 
+
947  if (funcCode == SCALED_INVERSE_NORM ||
+
948  funcCode == SCALED_INVERSE_PRODUCT ||
+
949  funcCode == SCALED_INVERSE_DISTANCE)
+
950  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
951 
+
952  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
+
953  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
954 
+
955  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
+
956  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
957 
+
958  if (funcCode == DISTANCE ||
+
959  funcCode == INVERSE_DISTANCE ||
+
960  funcCode == SCALED_DISTANCE ||
+
961  funcCode == SCALED_INVERSE_DISTANCE ||
+ +
963  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
+
964 }
-

References DISTANCE, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, E_INVALID_PHASE_FUNC_NAME, INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, NORM, PRODUCT, QuESTAssert(), SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, and SCALED_PRODUCT.

+

References DISTANCE, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, E_INVALID_PHASE_FUNC_NAME, INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, NORM, PRODUCT, QuESTAssert(), SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, and SCALED_PRODUCT.

-

Referenced by applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -3849,34 +3849,34 @@

-

Definition at line 857 of file QuEST_validation.c.

-
857  {
-
858  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
859  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
860 
-
861  long long int maxInd;
-
862  long long int minInd;
-
863 
-
864  if (encoding == UNSIGNED) {
-
865  minInd = 0;
-
866  maxInd = (1LL << numQubits) - 1;
-
867  for (int v=0; v<numOverrides; v++)
-
868  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
-
869  }
-
870 
-
871  if (encoding == TWOS_COMPLEMENT) {
-
872  int numValQubits = numQubits - 1; // removing sign bit
-
873  minInd = - (1LL << numValQubits);
-
874  maxInd = (1LL << numValQubits) - 1;
-
875  for (int v=0; v<numOverrides; v++)
-
876  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
-
877  }
-
878 
-
879 }
+

Definition at line 862 of file QuEST_validation.c.

+
862  {
+
863  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
864  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
865 
+
866  long long int maxInd;
+
867  long long int minInd;
+
868 
+
869  if (encoding == UNSIGNED) {
+
870  minInd = 0;
+
871  maxInd = (1LL << numQubits) - 1;
+
872  for (int v=0; v<numOverrides; v++)
+
873  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
+
874  }
+
875 
+
876  if (encoding == TWOS_COMPLEMENT) {
+
877  int numValQubits = numQubits - 1; // removing sign bit
+
878  minInd = - (1LL << numValQubits);
+
879  maxInd = (1LL << numValQubits) - 1;
+
880  for (int v=0; v<numOverrides; v++)
+
881  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
+
882  }
+
883 
+
884 }
-

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFuncOverrides().

+

Referenced by applyPhaseFuncOverrides().

@@ -3942,72 +3942,73 @@

-

Definition at line 769 of file QuEST_validation.c.

-
769  {
-
770  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
-
771 
-
772  int hasFractionExpo = 0;
-
773  int hasNegativeExpo = 0;
-
774  for (int t=0; t<numTerms; t++) {
-
775  // this is only true if exponent is precisely an integer, else pow() will NaN
-
776  if (floor(exponents[t]) != exponents[t])
-
777  hasFractionExpo = 1;
-
778  if (exponents[t] < 0)
-
779  hasNegativeExpo = 1;
-
780  }
-
781 
-
782  // ensure negative exponents are supplied along with a zero-index override
-
783  if (hasNegativeExpo) {
-
784  int hasZeroOverride = 0;
-
785  for (int v=0; v<numOverrides; v++) {
-
786  if (overrideInds[v] == 0LL) {
-
787  hasZeroOverride = 1;
-
788  break;
-
789  }
-
790  }
-
791  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
-
792  }
-
793 
-
794  // ensure fractional powers not used with negative numbers, unless overriden
-
795  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
-
796  long long int numNegInds = (1LL << (numQubits-1));
-
797 
-
798  // immediately disqualify if insufficient overrides are given to cover every negative number
-
799  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
-
800 
-
801  int allNegsOverriden;
-
802 
-
803  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
-
804  if (numQubits < 16) {
-
805 
-
806  long long int negIsOverriden[numNegInds]; // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
-
807  for (int i=0; i<numNegInds; i++)
-
808  negIsOverriden[i] = 0;
+

Definition at line 773 of file QuEST_validation.c.

+
773  {
+
774  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
+
775 
+
776  int hasFractionExpo = 0;
+
777  int hasNegativeExpo = 0;
+
778  for (int t=0; t<numTerms; t++) {
+
779  // this is only true if exponent is precisely an integer, else pow() will NaN
+
780  if (floor(exponents[t]) != exponents[t])
+
781  hasFractionExpo = 1;
+
782  if (exponents[t] < 0)
+
783  hasNegativeExpo = 1;
+
784  }
+
785 
+
786  // ensure negative exponents are supplied along with a zero-index override
+
787  if (hasNegativeExpo) {
+
788  int hasZeroOverride = 0;
+
789  for (int v=0; v<numOverrides; v++) {
+
790  if (overrideInds[v] == 0LL) {
+
791  hasZeroOverride = 1;
+
792  break;
+
793  }
+
794  }
+
795  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
+
796  }
+
797 
+
798  // ensure fractional powers not used with negative numbers, unless overriden
+
799  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
+
800  long long int numNegInds = (1LL << (numQubits-1));
+
801 
+
802  // immediately disqualify if insufficient overrides are given to cover every negative number
+
803  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
+
804 
+
805  int allNegsOverriden;
+
806 
+
807  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
+
808  if (numQubits < 16) {
809 
-
810  for (int v=0; v<numOverrides; v++)
-
811  if (overrideInds[v] < 0)
-
812  negIsOverriden[ -1 - overrideInds[v] ] = 1;
-
813 
-
814  allNegsOverriden = 1;
-
815  for (int i=0; i<numNegInds; i++) {
-
816  if (!negIsOverriden[i]) {
-
817  allNegsOverriden = 0;
-
818  break;
-
819  }
-
820  }
-
821  }
-
822  // otherwise, we must trust the user, else impose significant slowdowns on good users
-
823  else {
-
824  allNegsOverriden = 1;
-
825  }
-
826 
-
827  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
-
828  }
-
829 }
+
810  // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
+
811  long long int negIsOverriden[32768]; // [numNegInds];
+
812  for (int i=0; i<numNegInds; i++)
+
813  negIsOverriden[i] = 0;
+
814 
+
815  for (int v=0; v<numOverrides; v++)
+
816  if (overrideInds[v] < 0)
+
817  negIsOverriden[ -1 - overrideInds[v] ] = 1;
+
818 
+
819  allNegsOverriden = 1;
+
820  for (int i=0; i<numNegInds; i++) {
+
821  if (!negIsOverriden[i]) {
+
822  allNegsOverriden = 0;
+
823  break;
+
824  }
+
825  }
+
826  }
+
827  // otherwise, we must trust the user, else impose significant slowdowns on good users
+
828  else {
+
829  allNegsOverriden = 1;
+
830  }
+
831 
+
832  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
+
833  }
+
834 }
-

References E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, E_INVALID_NUM_PHASE_FUNC_TERMS, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, QuESTAssert(), and TWOS_COMPLEMENT.

+

References E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, E_INVALID_NUM_PHASE_FUNC_TERMS, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, QuESTAssert(), and TWOS_COMPLEMENT.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -4037,14 +4038,14 @@

-

Definition at line 547 of file QuEST_validation.c.

- @@ -4092,26 +4093,26 @@

-

Definition at line 753 of file QuEST_validation.c.

-
753  {
- -
755 
-
756  int i=0;
-
757  for (int r=0; r<numRegs; r++) {
-
758  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+

Definition at line 757 of file QuEST_validation.c.

+
757  {
+
759 
-
760  for (int q=0; q < numQubitsPerReg[r]; q++) {
-
761  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
762  i++;
-
763  }
-
764  }
-
765 
-
766  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
-
767 }
+
760  int i=0;
+
761  for (int r=0; r<numRegs; r++) {
+
762  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
763 
+
764  for (int q=0; q < numQubitsPerReg[r]; q++) {
+
765  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
+
766  i++;
+
767  }
+
768  }
+
769 
+
770  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
+
771 }
-

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_NUM_SUBREGISTERS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, Qureg::numQubitsRepresented, and QuESTAssert().

+

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_NUM_SUBREGISTERS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -4141,14 +4142,14 @@

-

Definition at line 535 of file QuEST_validation.c.

-
535  {
- -
537 }
+

Definition at line 539 of file QuEST_validation.c.

+
539  {
+ +
541 }
-

References E_SECOND_ARG_MUST_BE_STATEVEC, Qureg::isDensityMatrix, and QuESTAssert().

+

References E_SECOND_ARG_MUST_BE_STATEVEC, Qureg::isDensityMatrix, and QuESTAssert().

-

Referenced by calcFidelity(), and initPureState().

+

Referenced by calcFidelity(), and initPureState().

@@ -4184,13 +4185,13 @@

-

Definition at line 373 of file QuEST_validation.c.

-
373  {
-
374  long long int stateMax = 1LL << qureg.numQubitsRepresented;
-
375  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
-
376 }
+

Definition at line 377 of file QuEST_validation.c.

+
377  {
+
378  long long int stateMax = 1LL << qureg.numQubitsRepresented;
+
379  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
+
380 }
-

References E_INVALID_STATE_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_STATE_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

Referenced by initClassicalState().

@@ -4222,14 +4223,14 @@

-

Definition at line 511 of file QuEST_validation.c.

-

@@ -4265,14 +4266,14 @@

-

Definition at line 396 of file QuEST_validation.c.

- @@ -4308,16 +4309,16 @@

-

Definition at line 699 of file QuEST_validation.c.

-
699  {
-
700  int isEven = (order % 2) == 0;
-
701  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
-
702  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
-
703 }
+

Definition at line 703 of file QuEST_validation.c.

+
703  {
+
704  int isEven = (order % 2) == 0;
+
705  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
+
706  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
+
707 }
-

References E_INVALID_TROTTER_ORDER, E_INVALID_TROTTER_REPS, and QuESTAssert().

+

References E_INVALID_TROTTER_ORDER, E_INVALID_TROTTER_REPS, and QuESTAssert().

-

Referenced by applyTrotterCircuit().

+

Referenced by applyTrotterCircuit().

@@ -4347,15 +4348,15 @@

-

Definition at line 564 of file QuEST_validation.c.

-
564  {
-
565  validateProb(prob, caller);
-
566  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
-
567 }
+

Definition at line 568 of file QuEST_validation.c.

+
568  {
+
569  validateProb(prob, caller);
+
570  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
+
571 }
-

References E_INVALID_TWO_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_TWO_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixTwoQubitDephasing().

+

Referenced by mixTwoQubitDephasing().

@@ -4385,15 +4386,15 @@

-

Definition at line 579 of file QuEST_validation.c.

-
579  {
-
580  validateProb(prob, caller);
-
581  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
-
582 }
+

Definition at line 583 of file QuEST_validation.c.

+
583  {
+
584  validateProb(prob, caller);
+
585  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
+
586 }
-

References E_INVALID_TWO_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_TWO_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixTwoQubitDepolarising().

+

Referenced by mixTwoQubitDepolarising().

@@ -4435,22 +4436,22 @@

-

Definition at line 618 of file QuEST_validation.c.

-
618  {
-
619  int opNumQubits = 2;
-
620  int superOpNumQubits = 2*opNumQubits;
-
621  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
622  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
-
623 
-
624  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
625 
-
626  int isPos = isCompletelyPositiveMap4(ops, numOps);
-
627  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
628 }
+

Definition at line 622 of file QuEST_validation.c.

+
622  {
+
623  int opNumQubits = 2;
+
624  int superOpNumQubits = 2*opNumQubits;
+
625  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
626  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
+
627 
+
628  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
629 
+
630  int isPos = isCompletelyPositiveMap4(ops, numOps);
+
631  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
632 }
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, isCompletelyPositiveMap4(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

+

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, isCompletelyPositiveMap4(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

-

Referenced by mixTwoQubitKrausMap().

+

Referenced by mixTwoQubitKrausMap().

@@ -4486,15 +4487,15 @@

-

Definition at line 477 of file QuEST_validation.c.

- @@ -4536,16 +4537,16 @@

-

Definition at line 410 of file QuEST_validation.c.

-
410  {
-
411  validateTarget(qureg, qubit1, caller);
-
412  validateTarget(qureg, qubit2, caller);
-
413  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
-
414 }
+

Definition at line 414 of file QuEST_validation.c.

+
414  {
+
415  validateTarget(qureg, qubit1, caller);
+
416  validateTarget(qureg, qubit2, caller);
+
417  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
+
418 }
-

References E_TARGETS_NOT_UNIQUE, QuESTAssert(), and validateTarget().

+

References E_TARGETS_NOT_UNIQUE, QuESTAssert(), and validateTarget().

-

Referenced by mixTwoQubitDephasing(), mixTwoQubitDepolarising(), sqrtSwapGate(), and swapGate().

+

Referenced by mixTwoQubitDephasing(), mixTwoQubitDepolarising(), sqrtSwapGate(), and swapGate().

@@ -4581,14 +4582,14 @@

-

Definition at line 503 of file QuEST_validation.c.

-
503  {
- -
505 }
+

Definition at line 507 of file QuEST_validation.c.

+
507  {
+ +
509 }
-

References E_NON_UNITARY_COMPLEX_PAIR, isComplexPairUnitary(), and QuESTAssert().

+

References E_NON_UNITARY_COMPLEX_PAIR, isComplexPairUnitary(), and QuESTAssert().

-

Referenced by compactUnitary(), and controlledCompactUnitary().

+

Referenced by compactUnitary(), and controlledCompactUnitary().

@@ -4618,14 +4619,14 @@

-

Definition at line 507 of file QuEST_validation.c.

-
507  {
-
508  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
-
509 }
+

Definition at line 511 of file QuEST_validation.c.

+
511  {
+
512  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
+
513 }
-

References E_ZERO_VECTOR, getVectorMagnitude(), and QuESTAssert().

+

References E_ZERO_VECTOR, getVectorMagnitude(), and QuESTAssert().

-

Referenced by controlledRotateAroundAxis(), and rotateAroundAxis().

+

Referenced by controlledRotateAroundAxis(), and rotateAroundAxis().

@@ -4644,7 +4645,7 @@

Definition at line 30 of file QuEST_validation.c.

-

Referenced by validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

+

Referenced by validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

@@ -4670,7 +4671,7 @@

Definition at line 116 of file QuEST_validation.c.

-

Referenced by QuESTAssert(), validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

+

Referenced by QuESTAssert(), validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

@@ -4679,35 +4680,35 @@

pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
@ E_NUM_AMPS_EXCEED_TYPE
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
@ E_MISMATCHING_PAULI_HAMIL_DIAGONAL_OP_SIZE
@ E_INVALID_QUBIT_OUTCOME
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
-
int isMatrix2Unitary(ComplexMatrix2 u)
+
int isMatrix2Unitary(ComplexMatrix2 u)
@ E_PAULI_HAMIL_NOT_DIAGONAL
@ PAULI_Z
Definition: QuEST.h:96
@ DISTANCE
Definition: QuEST.h:234
@ E_INVALID_NUM_PHASE_FUNC_TERMS
@ E_INVALID_PAULI_CODE
@ E_NON_UNITARY_MATRIX
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
+
void validateHamilParams(int numQubits, int numTerms, const char *caller)
@ PAULI_I
Definition: QuEST.h:96
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
+
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
@ E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
@ E_INVALID_ELEM_INDEX
-
int isMatrix4Unitary(ComplexMatrix4 u)
+
int isMatrix4Unitary(ComplexMatrix4 u)
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
@ E_MISMATCHING_QUREG_TYPES
-
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
-
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
+
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
+
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
-
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
+
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
@ E_INVALID_QUBIT_INDEX
@ E_INVALID_PHASE_FUNC_NAME
-
void validateProb(qreal prob, const char *caller)
+
void validateProb(qreal prob, const char *caller)
@ E_INVALID_BIT_ENCODING
@ NORM
Definition: QuEST.h:232
@ E_NON_UNITARY_COMPLEX_PAIR
@@ -4724,27 +4725,27 @@

@ E_INVALID_NUM_SUM_TERMS
@ E_DEFINED_ONLY_FOR_STATEVECS
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
+
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
+
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
-
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
+
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
@ E_NEGATIVE_EXPONENT_MULTI_VAR
-
void validateControl(Qureg qureg, int controlQubit, const char *caller)
-
#define macro_isMatrixUnitary(m, dim, retVal)
+
void validateControl(Qureg qureg, int controlQubit, const char *caller)
+
#define macro_isMatrixUnitary(m, dim, retVal)
@ PAULI_X
Definition: QuEST.h:96
@ E_INVALID_PROB
-
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
-
int isMatrixNUnitary(ComplexMatrixN u)
+
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
+
int isMatrixNUnitary(ComplexMatrixN u)
@ E_QUBITS_NOT_UNIQUE
@ E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX
@ E_CONTROL_TARGET_COLLISION
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
+
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
@ E_DEFINED_ONLY_FOR_DENSMATRS
@ E_INVALID_KRAUS_OPS
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
@ E_INVALID_STATE_INDEX
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
int areUniqueQubits(int *qubits, int numQubits)
+
int areUniqueQubits(int *qubits, int numQubits)
@ E_TARGET_IN_CONTROLS
@ E_INVALID_NUM_QUBITS
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
@@ -4755,8 +4756,8 @@

enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
int isValidPauliCode(enum pauliOpType code)
+
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
+
int isValidPauliCode(enum pauliOpType code)
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
@ E_INVALID_TARGET_QUBIT
@ E_COMPLEX_MATRIX_NOT_INIT
@@ -4775,7 +4776,7 @@

@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
static const char * errorMessages[]
-
void QuESTAssert(int isValid, ErrorCode code, const char *func)
+
void QuESTAssert(int isValid, ErrorCode code, const char *func)
@ E_INVALID_NUM_AMPS
@ E_COLLAPSE_STATE_ZERO_PROB
@ E_TARGETS_NOT_UNIQUE
@@ -4788,11 +4789,11 @@

@ PRODUCT
Definition: QuEST.h:233
char errMsgBuffer[1024]
@ E_INVALID_NUM_CREATE_QUBITS
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
+
void validateDiagOpInit(DiagonalOp op, const char *caller)
@ E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
int numQubits
Definition: QuEST.h:188
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
+
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
@@ -4807,20 +4808,20 @@

@ E_FRACTIONAL_EXPONENT_MULTI_VAR
qreal real
Definition: QuEST.h:105
@ E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1399
-
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
+
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1414
+
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
qreal imag
Definition: QuEST.h:106
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
+
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
@ E_INVALID_NUM_ELEMS
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
@ E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE
@ E_INVALID_NUM_TARGETS
@ E_SYS_TOO_BIG_TO_PRINT
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
int isComplexPairUnitary(Complex alpha, Complex beta)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
+
int isComplexPairUnitary(Complex alpha, Complex beta)
+
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
@ E_DIAGONAL_OP_NOT_INITIALISED
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
@ E_SUCCESS
diff --git a/docs/QuEST__validation_8c_source.html b/docs/QuEST__validation_8c_source.html index 1af35c390..c8929fbb8 100644 --- a/docs/QuEST__validation_8c_source.html +++ b/docs/QuEST__validation_8c_source.html @@ -27,7 +27,7 @@ @@ -246,849 +246,854 @@
196  [E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC] = "Phase functions DISTANCE, INVERSE_DISTANCE, SCALED_DISTANCE and SCALED_INVERSE_DISTANCE require a strictly even number of sub-registers."
197 };
198 
-
199 void exitWithError(const char* msg, const char* func) {
+
199 void default_invalidQuESTInputError(const char* errMsg, const char* errFunc) {
200  printf("!!!\n");
-
201  printf("QuEST Error in function %s: %s\n", func, msg);
+
201  printf("QuEST Error in function %s: %s\n", errFunc, errMsg);
202  printf("!!!\n");
203  printf("exiting..\n");
204  exit(1);
205 }
206 
-
207 #pragma weak invalidQuESTInputError
-
208 void invalidQuESTInputError(const char* errMsg, const char* errFunc) {
-
209  exitWithError(errMsg, errFunc);
-
210 }
-
211 
-
212 void QuESTAssert(int isValid, ErrorCode code, const char* func){
-
213  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
-
214 }
+
207 #ifndef _WIN32
+
208 #pragma weak invalidQuESTInputError
+
209 void invalidQuESTInputError(const char* errMsg, const char* errFunc) {
+
210  default_invalidQuESTInputError(errMsg, errFunc);
+
211 }
+
212 #else
+
213 #pragma comment(linker, "/alternatename:invalidQuESTInputError=default_invalidQuESTInputError")
+
214 #endif
215 
-
216 int isComplexUnit(Complex alpha) {
-
217  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
+
216 void QuESTAssert(int isValid, ErrorCode code, const char* func){
+
217  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
218 }
219 
-
220 int isVectorUnit(qreal ux, qreal uy, qreal uz) {
-
221  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
+
220 int isComplexUnit(Complex alpha) {
+
221  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
222 }
223 
- -
225  return ( absReal( -1
-
226  + alpha.real*alpha.real
-
227  + alpha.imag*alpha.imag
-
228  + beta.real*beta.real
-
229  + beta.imag*beta.imag) < REAL_EPS );
-
230 }
-
231 
-
232 #define macro_isMatrixUnitary(m, dim, retVal) { \
-
233  /* elemRe_ and elemIm_ must not exist in caller scope */ \
-
234  qreal elemRe_, elemIm_; \
-
235  retVal = 1; \
-
236  /* check m * ConjugateTranspose(m) == Identity */ \
-
237  for (int r=0; r < (dim); r++) { \
-
238  for (int c=0; c < (dim); c++) { \
-
239  /* m[r][...] * ConjugateTranspose(m)[...][c] */ \
-
240  elemRe_ = 0; \
-
241  elemIm_ = 0; \
-
242  for (int i=0; i < (dim); i++) { \
-
243  /* m[r][i] * conj(m[c][i]) */ \
-
244  elemRe_ += m.real[r][i]*m.real[c][i] + m.imag[r][i]*m.imag[c][i]; \
-
245  elemIm_ += m.imag[r][i]*m.real[c][i] - m.real[r][i]*m.imag[c][i]; \
-
246  } \
-
247  /* check distance from identity */ \
-
248  if ((absReal(elemIm_) > REAL_EPS) || \
-
249  (r == c && absReal(elemRe_ - 1) > REAL_EPS) || \
-
250  (r != c && absReal(elemRe_ ) > REAL_EPS)) { \
-
251  retVal = 0; \
-
252  break; \
-
253  } \
-
254  } \
-
255  if (retVal == 0) \
-
256  break; \
-
257  } \
-
258 }
- -
260  int dim = 2;
-
261  int retVal;
-
262  macro_isMatrixUnitary(u, dim, retVal);
-
263  return retVal;
-
264 }
- -
266  int dim = 4;
-
267  int retVal;
-
268  macro_isMatrixUnitary(u, dim, retVal);
-
269  return retVal;
-
270 }
- -
272  int dim = 1 << u.numQubits;
-
273  int retVal;
-
274  macro_isMatrixUnitary(u, dim, retVal);
-
275  return retVal;
-
276 }
-
277 
-
278 #define macro_isCompletelyPositiveMap(ops, numOps, opDim) { \
-
279  for (int r=0; r<(opDim); r++) { \
-
280  for (int c=0; c<(opDim); c++) { \
-
281  qreal elemRe_ = 0; \
-
282  qreal elemIm_ = 0; \
-
283  for (int n=0; n<(numOps); n++) { \
-
284  for (int k=0; k<(opDim); k++) { \
-
285  elemRe_ += ops[n].real[k][r]*ops[n].real[k][c] + ops[n].imag[k][r]*ops[n].imag[k][c]; \
-
286  elemIm_ += ops[n].real[k][r]*ops[n].imag[k][c] - ops[n].imag[k][r]*ops[n].real[k][c]; \
-
287  } \
-
288  } \
-
289  qreal dist_ = absReal(elemIm_) + absReal(elemRe_ - ((r==c)? 1:0)); \
-
290  if (dist_ > REAL_EPS) \
-
291  return 0; \
-
292  } \
-
293  } \
-
294  return 1; \
-
295 }
- -
297  macro_isCompletelyPositiveMap(ops, numOps, 2);
-
298 }
- -
300  macro_isCompletelyPositiveMap(ops, numOps, 4);
-
301 }
- -
303  int opDim = 1 << ops[0].numQubits;
-
304  macro_isCompletelyPositiveMap(ops, numOps, opDim);
+
224 int isVectorUnit(qreal ux, qreal uy, qreal uz) {
+
225  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
+
226 }
+
227 
+ +
229  return ( absReal( -1
+
230  + alpha.real*alpha.real
+
231  + alpha.imag*alpha.imag
+
232  + beta.real*beta.real
+
233  + beta.imag*beta.imag) < REAL_EPS );
+
234 }
+
235 
+
236 #define macro_isMatrixUnitary(m, dim, retVal) { \
+
237  /* elemRe_ and elemIm_ must not exist in caller scope */ \
+
238  qreal elemRe_, elemIm_; \
+
239  retVal = 1; \
+
240  /* check m * ConjugateTranspose(m) == Identity */ \
+
241  for (int r=0; r < (dim); r++) { \
+
242  for (int c=0; c < (dim); c++) { \
+
243  /* m[r][...] * ConjugateTranspose(m)[...][c] */ \
+
244  elemRe_ = 0; \
+
245  elemIm_ = 0; \
+
246  for (int i=0; i < (dim); i++) { \
+
247  /* m[r][i] * conj(m[c][i]) */ \
+
248  elemRe_ += m.real[r][i]*m.real[c][i] + m.imag[r][i]*m.imag[c][i]; \
+
249  elemIm_ += m.imag[r][i]*m.real[c][i] - m.real[r][i]*m.imag[c][i]; \
+
250  } \
+
251  /* check distance from identity */ \
+
252  if ((absReal(elemIm_) > REAL_EPS) || \
+
253  (r == c && absReal(elemRe_ - 1) > REAL_EPS) || \
+
254  (r != c && absReal(elemRe_ ) > REAL_EPS)) { \
+
255  retVal = 0; \
+
256  break; \
+
257  } \
+
258  } \
+
259  if (retVal == 0) \
+
260  break; \
+
261  } \
+
262 }
+ +
264  int dim = 2;
+
265  int retVal;
+
266  macro_isMatrixUnitary(u, dim, retVal);
+
267  return retVal;
+
268 }
+ +
270  int dim = 4;
+
271  int retVal;
+
272  macro_isMatrixUnitary(u, dim, retVal);
+
273  return retVal;
+
274 }
+ +
276  int dim = 1 << u.numQubits;
+
277  int retVal;
+
278  macro_isMatrixUnitary(u, dim, retVal);
+
279  return retVal;
+
280 }
+
281 
+
282 #define macro_isCompletelyPositiveMap(ops, numOps, opDim) { \
+
283  for (int r=0; r<(opDim); r++) { \
+
284  for (int c=0; c<(opDim); c++) { \
+
285  qreal elemRe_ = 0; \
+
286  qreal elemIm_ = 0; \
+
287  for (int n=0; n<(numOps); n++) { \
+
288  for (int k=0; k<(opDim); k++) { \
+
289  elemRe_ += ops[n].real[k][r]*ops[n].real[k][c] + ops[n].imag[k][r]*ops[n].imag[k][c]; \
+
290  elemIm_ += ops[n].real[k][r]*ops[n].imag[k][c] - ops[n].imag[k][r]*ops[n].real[k][c]; \
+
291  } \
+
292  } \
+
293  qreal dist_ = absReal(elemIm_) + absReal(elemRe_ - ((r==c)? 1:0)); \
+
294  if (dist_ > REAL_EPS) \
+
295  return 0; \
+
296  } \
+
297  } \
+
298  return 1; \
+
299 }
+ +
301  macro_isCompletelyPositiveMap(ops, numOps, 2);
+
302 }
+ +
304  macro_isCompletelyPositiveMap(ops, numOps, 4);
305 }
-
306 
- -
308  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
+ +
307  int opDim = 1 << ops[0].numQubits;
+
308  macro_isCompletelyPositiveMap(ops, numOps, opDim);
309 }
310 
-
311 int areUniqueQubits(int* qubits, int numQubits) {
-
312  long long int mask = 0;
-
313  long long int bit;
-
314  for (int q=0; q < numQubits; q++) {
-
315  bit = 1LL << qubits[q];
-
316  if (mask & bit)
-
317  return 0;
-
318  mask |= bit;
-
319  }
-
320  return 1;
-
321 }
-
322 
-
324 unsigned int calcLog2(long unsigned int num) {
-
325  unsigned int l = 0;
-
326  while (num >>= 1)
-
327  l++;
-
328  return l;
-
329 }
-
330 
-
331 void validateNumRanks(int numRanks, const char* caller) {
-
332 
-
333  /* silly but robust way to determine if numRanks is a power of 2,
-
334  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
-
335  * system / precsision dependent
-
336  */
-
337  int isValid = 0;
-
338  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
-
339  if (exp2 == numRanks)
-
340  isValid = 1;
-
341 
-
342  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
-
343 }
-
344 
-
345 void validateNumQubitsInQureg(int numQubits, int numRanks, const char* caller) {
-
346  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
347 
-
348  // mustn't be more amplitudes than can fit in the type
-
349  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
350  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+ +
312  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
+
313 }
+
314 
+
315 int areUniqueQubits(int* qubits, int numQubits) {
+
316  long long int mask = 0;
+
317  long long int bit;
+
318  for (int q=0; q < numQubits; q++) {
+
319  bit = 1LL << qubits[q];
+
320  if (mask & bit)
+
321  return 0;
+
322  mask |= bit;
+
323  }
+
324  return 1;
+
325 }
+
326 
+
328 unsigned int calcLog2(long unsigned int num) {
+
329  unsigned int l = 0;
+
330  while (num >>= 1)
+
331  l++;
+
332  return l;
+
333 }
+
334 
+
335 void validateNumRanks(int numRanks, const char* caller) {
+
336 
+
337  /* silly but robust way to determine if numRanks is a power of 2,
+
338  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
+
339  * system / precsision dependent
+
340  */
+
341  int isValid = 0;
+
342  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
+
343  if (exp2 == numRanks)
+
344  isValid = 1;
+
345 
+
346  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
+
347 }
+
348 
+
349 void validateNumQubitsInQureg(int numQubits, int numRanks, const char* caller) {
+
350  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
351 
-
352  // must be at least one amplitude per node
-
353  long unsigned int numAmps = (1UL<<numQubits);
-
354  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
-
355 }
-
356 
-
357 void validateNumQubitsInMatrix(int numQubits, const char* caller) {
-
358  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
+
352  // mustn't be more amplitudes than can fit in the type
+
353  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
354  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
355 
+
356  // must be at least one amplitude per node
+
357  long unsigned int numAmps = (1UL<<numQubits);
+
358  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
359 }
360 
-
361 void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char* caller) {
-
362  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
363 
-
364  // mustn't be more amplitudes than can fit in the type
-
365  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
366  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
361 void validateNumQubitsInMatrix(int numQubits, const char* caller) {
+
362  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
+
363 }
+
364 
+
365 void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char* caller) {
+
366  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
367 
-
368  // must be at least one amplitude per node
-
369  long unsigned int numAmps = (1UL<<numQubits);
-
370  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
371 }
-
372 
-
373 void validateStateIndex(Qureg qureg, long long int stateInd, const char* caller) {
-
374  long long int stateMax = 1LL << qureg.numQubitsRepresented;
-
375  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
-
376 }
-
377 
-
378 void validateAmpIndex(Qureg qureg, long long int ampInd, const char* caller) {
-
379  long long int indMax = 1LL << qureg.numQubitsRepresented;
-
380  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
-
381 }
-
382 
-
383 void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char* caller) {
-
384  validateAmpIndex(qureg, startInd, caller);
-
385  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
-
386  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
-
387 }
-
388 
-
389 void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char* caller) {
-
390  long long int indMax = 1LL << op.numQubits;
-
391  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
-
392  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
-
393  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
-
394 }
-
395 
-
396 void validateTarget(Qureg qureg, int targetQubit, const char* caller) {
-
397  QuESTAssert(targetQubit>=0 && targetQubit<qureg.numQubitsRepresented, E_INVALID_TARGET_QUBIT, caller);
+
368  // mustn't be more amplitudes than can fit in the type
+
369  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
370  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
371 
+
372  // must be at least one amplitude per node
+
373  long unsigned int numAmps = (1UL<<numQubits);
+
374  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
+
375 }
+
376 
+
377 void validateStateIndex(Qureg qureg, long long int stateInd, const char* caller) {
+
378  long long int stateMax = 1LL << qureg.numQubitsRepresented;
+
379  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
+
380 }
+
381 
+
382 void validateAmpIndex(Qureg qureg, long long int ampInd, const char* caller) {
+
383  long long int indMax = 1LL << qureg.numQubitsRepresented;
+
384  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
+
385 }
+
386 
+
387 void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char* caller) {
+
388  validateAmpIndex(qureg, startInd, caller);
+
389  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
+
390  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
+
391 }
+
392 
+
393 void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char* caller) {
+
394  long long int indMax = 1LL << op.numQubits;
+
395  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
+
396  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
+
397  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
398 }
399 
-
400 void validateControl(Qureg qureg, int controlQubit, const char* caller) {
-
401  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
+
400 void validateTarget(Qureg qureg, int targetQubit, const char* caller) {
+
401  QuESTAssert(targetQubit>=0 && targetQubit<qureg.numQubitsRepresented, E_INVALID_TARGET_QUBIT, caller);
402 }
403 
-
404 void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char* caller) {
-
405  validateTarget(qureg, targetQubit, caller);
-
406  validateControl(qureg, controlQubit, caller);
-
407  QuESTAssert(controlQubit != targetQubit, E_TARGET_IS_CONTROL, caller);
-
408 }
-
409 
-
410 void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char* caller) {
-
411  validateTarget(qureg, qubit1, caller);
-
412  validateTarget(qureg, qubit2, caller);
-
413  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
-
414 }
-
415 
-
416 void validateNumTargets(Qureg qureg, int numTargetQubits, const char* caller) {
-
417  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
+
404 void validateControl(Qureg qureg, int controlQubit, const char* caller) {
+
405  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
+
406 }
+
407 
+
408 void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char* caller) {
+
409  validateTarget(qureg, targetQubit, caller);
+
410  validateControl(qureg, controlQubit, caller);
+
411  QuESTAssert(controlQubit != targetQubit, E_TARGET_IS_CONTROL, caller);
+
412 }
+
413 
+
414 void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char* caller) {
+
415  validateTarget(qureg, qubit1, caller);
+
416  validateTarget(qureg, qubit2, caller);
+
417  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
418 }
419 
-
420 void validateNumControls(Qureg qureg, int numControlQubits, const char* caller) {
-
421  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
+
420 void validateNumTargets(Qureg qureg, int numTargetQubits, const char* caller) {
+
421  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
422 }
423 
-
424 void validateMultiTargets(Qureg qureg, int* targetQubits, int numTargetQubits, const char* caller) {
-
425  validateNumTargets(qureg, numTargetQubits, caller);
-
426  for (int i=0; i < numTargetQubits; i++)
-
427  validateTarget(qureg, targetQubits[i], caller);
-
428 
-
429  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
-
430 }
-
431 
-
432 void validateMultiControls(Qureg qureg, int* controlQubits, int numControlQubits, const char* caller) {
-
433  validateNumControls(qureg, numControlQubits, caller);
-
434  for (int i=0; i < numControlQubits; i++)
-
435  validateControl(qureg, controlQubits[i], caller);
-
436 
-
437  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
-
438 }
-
439 
-
440 void validateMultiQubits(Qureg qureg, int* qubits, int numQubits, const char* caller) {
-
441  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
-
442  for (int i=0; i < numQubits; i++)
-
443  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
444 
-
445  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
-
446 }
-
447 
-
448 void validateMultiControlsTarget(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, const char* caller) {
-
449  validateTarget(qureg, targetQubit, caller);
-
450  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
451  for (int i=0; i < numControlQubits; i++)
-
452  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
-
453 }
-
454 
-
455 void validateMultiControlsMultiTargets(Qureg qureg, int* controlQubits, int numControlQubits, int* targetQubits, int numTargetQubits, const char* caller) {
-
456  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
457  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
-
458  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
-
459  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
-
460  int overlap = ctrlMask & targMask;
-
461  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
-
462 }
-
463 
-
464 void validateControlState(int* controlState, int numControlQubits, const char* caller) {
-
465  for (int i=0; i < numControlQubits; i++)
-
466  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
-
467 }
-
468 
-
469 void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char* caller) {
-
470  QuESTAssert(qureg.numAmpsPerChunk >= (1LL << numTargets), E_CANNOT_FIT_MULTI_QUBIT_MATRIX, caller);
+
424 void validateNumControls(Qureg qureg, int numControlQubits, const char* caller) {
+
425  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
+
426 }
+
427 
+
428 void validateMultiTargets(Qureg qureg, int* targetQubits, int numTargetQubits, const char* caller) {
+
429  validateNumTargets(qureg, numTargetQubits, caller);
+
430  for (int i=0; i < numTargetQubits; i++)
+
431  validateTarget(qureg, targetQubits[i], caller);
+
432 
+
433  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
+
434 }
+
435 
+
436 void validateMultiControls(Qureg qureg, int* controlQubits, int numControlQubits, const char* caller) {
+
437  validateNumControls(qureg, numControlQubits, caller);
+
438  for (int i=0; i < numControlQubits; i++)
+
439  validateControl(qureg, controlQubits[i], caller);
+
440 
+
441  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
+
442 }
+
443 
+
444 void validateMultiQubits(Qureg qureg, int* qubits, int numQubits, const char* caller) {
+
445  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
446  for (int i=0; i < numQubits; i++)
+
447  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
+
448 
+
449  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
+
450 }
+
451 
+
452 void validateMultiControlsTarget(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, const char* caller) {
+
453  validateTarget(qureg, targetQubit, caller);
+
454  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
+
455  for (int i=0; i < numControlQubits; i++)
+
456  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
+
457 }
+
458 
+
459 void validateMultiControlsMultiTargets(Qureg qureg, int* controlQubits, int numControlQubits, int* targetQubits, int numTargetQubits, const char* caller) {
+
460  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
+
461  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
+
462  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
+
463  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
+
464  int overlap = ctrlMask & targMask;
+
465  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
+
466 }
+
467 
+
468 void validateControlState(int* controlState, int numControlQubits, const char* caller) {
+
469  for (int i=0; i < numControlQubits; i++)
+
470  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
471 }
472 
-
473 void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char* caller) {
- +
473 void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char* caller) {
+
474  QuESTAssert(qureg.numAmpsPerChunk >= (1LL << numTargets), E_CANNOT_FIT_MULTI_QUBIT_MATRIX, caller);
475 }
476 
-
477 void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char* caller) {
-
478  validateMultiQubitMatrixFitsInNode(qureg, 2, caller);
- -
480 }
-
481 
-
482 void validateMatrixInit(ComplexMatrixN matr, const char* caller) {
-
483 
-
484  /* note that for (most) compilers which don't automatically initialise
-
485  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
-
486  * succeeded. It can not be used to differentiate whether a user actually attempted
-
487  * to initialise or create their ComplexMatrixN instance.
-
488  */
-
489  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
-
490 }
-
491 
-
492 void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
-
493  validateMatrixInit(u, caller);
-
494  validateMultiQubitMatrixFitsInNode(qureg, numTargs, caller);
-
495  QuESTAssert(numTargs == u.numQubits, E_INVALID_UNITARY_SIZE, caller);
-
496 }
-
497 
-
498 void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
-
499  validateMultiQubitMatrix(qureg, u, numTargs, caller);
- -
501 }
-
502 
-
503 void validateUnitaryComplexPair(Complex alpha, Complex beta, const char* caller) {
- +
477 void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char* caller) {
+ +
479 }
+
480 
+
481 void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char* caller) {
+
482  validateMultiQubitMatrixFitsInNode(qureg, 2, caller);
+ +
484 }
+
485 
+
486 void validateMatrixInit(ComplexMatrixN matr, const char* caller) {
+
487 
+
488  /* note that for (most) compilers which don't automatically initialise
+
489  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
+
490  * succeeded. It can not be used to differentiate whether a user actually attempted
+
491  * to initialise or create their ComplexMatrixN instance.
+
492  */
+
493  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
+
494 }
+
495 
+
496 void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
+
497  validateMatrixInit(u, caller);
+
498  validateMultiQubitMatrixFitsInNode(qureg, numTargs, caller);
+
499  QuESTAssert(numTargs == u.numQubits, E_INVALID_UNITARY_SIZE, caller);
+
500 }
+
501 
+
502 void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
+
503  validateMultiQubitMatrix(qureg, u, numTargs, caller);
+
505 }
506 
-
507 void validateVector(Vector vec, const char* caller) {
-
508  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
+
507 void validateUnitaryComplexPair(Complex alpha, Complex beta, const char* caller) {
+
509 }
510 
-
511 void validateStateVecQureg(Qureg qureg, const char* caller) {
- +
511 void validateVector(Vector vec, const char* caller) {
+
512  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
513 }
514 
-
515 void validateDensityMatrQureg(Qureg qureg, const char* caller) {
- +
515 void validateStateVecQureg(Qureg qureg, const char* caller) {
+
517 }
518 
-
519 void validateOutcome(int outcome, const char* caller) {
-
520  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
+
519 void validateDensityMatrQureg(Qureg qureg, const char* caller) {
+
521 }
522 
-
523 void validateMeasurementProb(qreal prob, const char* caller) {
-
524  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
+
523 void validateOutcome(int outcome, const char* caller) {
+
524  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
525 }
526 
-
527 void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller) {
- +
527 void validateMeasurementProb(qreal prob, const char* caller) {
+
528  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
529 }
530 
-
531 void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller) {
- +
531 void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller) {
+
533 }
534 
-
535 void validateSecondQuregStateVec(Qureg qureg2, const char *caller) {
- +
535 void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller) {
+
537 }
538 
-
539 void validateFileOpened(int opened, char* fn, const char* caller) {
-
540  if (!opened) {
-
541 
- - -
544  }
-
545 }
-
546 
-
547 void validateProb(qreal prob, const char* caller) {
-
548  QuESTAssert(prob >= 0 && prob <= 1, E_INVALID_PROB, caller);
+
539 void validateSecondQuregStateVec(Qureg qureg2, const char *caller) {
+ +
541 }
+
542 
+
543 void validateFileOpened(int opened, char* fn, const char* caller) {
+
544  if (!opened) {
+
545 
+ + +
548  }
549 }
550 
-
551 void validateNormProbs(qreal prob1, qreal prob2, const char* caller) {
-
552  validateProb(prob1, caller);
-
553  validateProb(prob2, caller);
-
554 
-
555  qreal sum = prob1 + prob2;
-
556  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
-
557 }
-
558 
-
559 void validateOneQubitDephaseProb(qreal prob, const char* caller) {
-
560  validateProb(prob, caller);
-
561  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
-
562 }
-
563 
-
564 void validateTwoQubitDephaseProb(qreal prob, const char* caller) {
-
565  validateProb(prob, caller);
-
566  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
-
567 }
-
568 
-
569 void validateOneQubitDepolProb(qreal prob, const char* caller) {
-
570  validateProb(prob, caller);
-
571  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
572 }
-
573 
-
574 void validateOneQubitDampingProb(qreal prob, const char* caller) {
-
575  validateProb(prob, caller);
-
576  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
577 }
-
578 
-
579 void validateTwoQubitDepolProb(qreal prob, const char* caller) {
-
580  validateProb(prob, caller);
-
581  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
-
582 }
-
583 
-
584 void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char* caller) {
-
585  validateProb(probX, caller);
-
586  validateProb(probY, caller);
-
587  validateProb(probZ, caller);
-
588 
-
589  qreal probNoError = 1 - probX - probY - probZ;
-
590  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
591  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
592  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
593 }
-
594 
-
595 void validatePauliCodes(enum pauliOpType* pauliCodes, int numPauliCodes, const char* caller) {
-
596  for (int i=0; i < numPauliCodes; i++) {
-
597  enum pauliOpType code = pauliCodes[i];
- -
599  }
-
600 }
-
601 
-
602 void validateNumPauliSumTerms(int numTerms, const char* caller) {
-
603  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
+
551 void validateProb(qreal prob, const char* caller) {
+
552  QuESTAssert(prob >= 0 && prob <= 1, E_INVALID_PROB, caller);
+
553 }
+
554 
+
555 void validateNormProbs(qreal prob1, qreal prob2, const char* caller) {
+
556  validateProb(prob1, caller);
+
557  validateProb(prob2, caller);
+
558 
+
559  qreal sum = prob1 + prob2;
+
560  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
+
561 }
+
562 
+
563 void validateOneQubitDephaseProb(qreal prob, const char* caller) {
+
564  validateProb(prob, caller);
+
565  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
+
566 }
+
567 
+
568 void validateTwoQubitDephaseProb(qreal prob, const char* caller) {
+
569  validateProb(prob, caller);
+
570  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
+
571 }
+
572 
+
573 void validateOneQubitDepolProb(qreal prob, const char* caller) {
+
574  validateProb(prob, caller);
+
575  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
+
576 }
+
577 
+
578 void validateOneQubitDampingProb(qreal prob, const char* caller) {
+
579  validateProb(prob, caller);
+
580  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
+
581 }
+
582 
+
583 void validateTwoQubitDepolProb(qreal prob, const char* caller) {
+
584  validateProb(prob, caller);
+
585  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
+
586 }
+
587 
+
588 void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char* caller) {
+
589  validateProb(probX, caller);
+
590  validateProb(probY, caller);
+
591  validateProb(probZ, caller);
+
592 
+
593  qreal probNoError = 1 - probX - probY - probZ;
+
594  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
595  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
596  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
597 }
+
598 
+
599 void validatePauliCodes(enum pauliOpType* pauliCodes, int numPauliCodes, const char* caller) {
+
600  for (int i=0; i < numPauliCodes; i++) {
+
601  enum pauliOpType code = pauliCodes[i];
+ +
603  }
604 }
605 
-
606 void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2* ops, int numOps, const char* caller) {
-
607  int opNumQubits = 1;
-
608  int superOpNumQubits = 2*opNumQubits;
-
609  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
610  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
-
611 
-
612  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
613 
-
614  int isPos = isCompletelyPositiveMap2(ops, numOps);
-
615  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
616 }
-
617 
-
618 void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4* ops, int numOps, const char* caller) {
-
619  int opNumQubits = 2;
-
620  int superOpNumQubits = 2*opNumQubits;
-
621  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
622  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
-
623 
-
624  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
625 
-
626  int isPos = isCompletelyPositiveMap4(ops, numOps);
-
627  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
628 }
+
606 void validateNumPauliSumTerms(int numTerms, const char* caller) {
+
607  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
+
608 }
+
609 
+
610 void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2* ops, int numOps, const char* caller) {
+
611  int opNumQubits = 1;
+
612  int superOpNumQubits = 2*opNumQubits;
+
613  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
614  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
+
615 
+
616  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
617 
+
618  int isPos = isCompletelyPositiveMap2(ops, numOps);
+
619  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
620 }
+
621 
+
622 void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4* ops, int numOps, const char* caller) {
+
623  int opNumQubits = 2;
+
624  int superOpNumQubits = 2*opNumQubits;
+
625  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
626  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
+
627 
+
628  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
629 
-
630 void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN* ops, int numOps, const char* caller) {
-
631  int opNumQubits = numTargs;
-
632  int superOpNumQubits = 2*opNumQubits;
-
633  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
634  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
-
635 
-
636  for (int n=0; n<numOps; n++) {
-
637  validateMatrixInit(ops[n], __func__);
-
638  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
-
639  }
-
640 
-
641  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
642 
-
643  int isPos = isCompletelyPositiveMapN(ops, numOps);
-
644  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
645 }
-
646 
-
647 void validateHamilParams(int numQubits, int numTerms, const char* caller) {
-
648  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
+
630  int isPos = isCompletelyPositiveMap4(ops, numOps);
+
631  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
632 }
+
633 
+
634 void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN* ops, int numOps, const char* caller) {
+
635  int opNumQubits = numTargs;
+
636  int superOpNumQubits = 2*opNumQubits;
+
637  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
638  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
+
639 
+
640  for (int n=0; n<numOps; n++) {
+
641  validateMatrixInit(ops[n], __func__);
+
642  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
+
643  }
+
644 
+
645  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
646 
+
647  int isPos = isCompletelyPositiveMapN(ops, numOps);
+
648  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
649 }
650 
-
651 void validatePauliHamil(PauliHamil hamil, const char* caller) {
-
652  validateHamilParams(hamil.numQubits, hamil.numSumTerms, caller);
-
653  validatePauliCodes(hamil.pauliCodes, hamil.numSumTerms*hamil.numQubits, caller);
-
654 }
-
655 
-
656 void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char* caller) {
- +
651 void validateHamilParams(int numQubits, int numTerms, const char* caller) {
+
652  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
+
653 }
+
654 
+
655 void validatePauliHamil(PauliHamil hamil, const char* caller) {
+
656  validateHamilParams(hamil.numQubits, hamil.numSumTerms, caller);
+
657  validatePauliCodes(hamil.pauliCodes, hamil.numSumTerms*hamil.numQubits, caller);
658 }
659 
-
660 void validateHamilFileParams(int numQubits, int numTerms, FILE* file, char* fn, const char* caller) {
-
661  if (!(numQubits > 0 && numTerms > 0)) {
-
662  fclose(file);
+
660 void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char* caller) {
+ +
662 }
663 
- - -
666  }
-
667 }
-
668 
-
669 void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
-
670  if (!parsed) {
- -
672  fclose(file);
-
673 
- - -
676  }
-
677 }
-
678 
-
679 void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
-
680  if (!parsed) {
- -
682  fclose(file);
-
683 
- - -
686  }
-
687 }
-
688 
-
689 void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE* file, char* fn, const char* caller) {
-
690  if (!isValidPauliCode(code)) {
- -
692  fclose(file);
-
693 
- - -
696  }
-
697 }
-
698 
-
699 void validateTrotterParams(int order, int reps, const char* caller) {
-
700  int isEven = (order % 2) == 0;
-
701  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
-
702  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
-
703 }
-
704 
-
705 void validateDiagOpInit(DiagonalOp op, const char* caller) {
-
706  QuESTAssert(op.real != NULL && op.imag != NULL, E_DIAGONAL_OP_NOT_INITIALISED, caller);
+
664 void validateHamilFileParams(int numQubits, int numTerms, FILE* file, char* fn, const char* caller) {
+
665  if (!(numQubits > 0 && numTerms > 0)) {
+
666  fclose(file);
+
667 
+ + +
670  }
+
671 }
+
672 
+
673 void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
+
674  if (!parsed) {
+ +
676  fclose(file);
+
677 
+ + +
680  }
+
681 }
+
682 
+
683 void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
+
684  if (!parsed) {
+ +
686  fclose(file);
+
687 
+ + +
690  }
+
691 }
+
692 
+
693 void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE* file, char* fn, const char* caller) {
+
694  if (!isValidPauliCode(code)) {
+ +
696  fclose(file);
+
697 
+ + +
700  }
+
701 }
+
702 
+
703 void validateTrotterParams(int order, int reps, const char* caller) {
+
704  int isEven = (order % 2) == 0;
+
705  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
+
706  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
707 }
708 
-
709 void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char* caller) {
-
710  validateDiagOpInit(op, caller);
- -
712 }
-
713 
-
714 void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller) {
- -
716 
-
717  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++)
-
718  QuESTAssert(
-
719  hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z,
- -
721 }
-
722 
-
723 void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller) {
-
724  // hamil itself already validated as general Pauli Hamiltonian
-
725 
-
726  // destroy hamil before raising exceptions if validation fails
-
727  int isValid;
-
728 
-
729  // mustn't be more elements than can fit in the type
-
730  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
731  isValid = hamil.numQubits <= maxQubits;
-
732  if (!isValid)
-
733  destroyPauliHamil(hamil);
-
734  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
-
735 
-
736  // must be at least one amplitude per node
-
737  long unsigned int numElems = (1UL<<hamil.numQubits);
-
738  isValid = numElems >= numRanks;
-
739  if (!isValid)
-
740  destroyPauliHamil(hamil);
-
741  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
742 
-
743  // must contain only I and Z
-
744  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
-
745  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
-
746  if (!isValid)
-
747  destroyPauliHamil(hamil);
-
748 
-
749  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
-
750  }
-
751 }
-
752 
-
753 void validateQubitSubregs(Qureg qureg, int* qubits, int* numQubitsPerReg, const int numRegs, const char* caller) {
- -
755 
-
756  int i=0;
-
757  for (int r=0; r<numRegs; r++) {
-
758  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
709 void validateDiagOpInit(DiagonalOp op, const char* caller) {
+
710  QuESTAssert(op.real != NULL && op.imag != NULL, E_DIAGONAL_OP_NOT_INITIALISED, caller);
+
711 }
+
712 
+
713 void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char* caller) {
+
714  validateDiagOpInit(op, caller);
+ +
716 }
+
717 
+
718 void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller) {
+ +
720 
+
721  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++)
+
722  QuESTAssert(
+
723  hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z,
+ +
725 }
+
726 
+
727 void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller) {
+
728  // hamil itself already validated as general Pauli Hamiltonian
+
729 
+
730  // destroy hamil before raising exceptions if validation fails
+
731  int isValid;
+
732 
+
733  // mustn't be more elements than can fit in the type
+
734  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
735  isValid = hamil.numQubits <= maxQubits;
+
736  if (!isValid)
+
737  destroyPauliHamil(hamil);
+
738  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
+
739 
+
740  // must be at least one amplitude per node
+
741  long unsigned int numElems = (1UL<<hamil.numQubits);
+
742  isValid = numElems >= numRanks;
+
743  if (!isValid)
+
744  destroyPauliHamil(hamil);
+
745  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
+
746 
+
747  // must contain only I and Z
+
748  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
+
749  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
+
750  if (!isValid)
+
751  destroyPauliHamil(hamil);
+
752 
+
753  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
+
754  }
+
755 }
+
756 
+
757 void validateQubitSubregs(Qureg qureg, int* qubits, int* numQubitsPerReg, const int numRegs, const char* caller) {
+
759 
-
760  for (int q=0; q < numQubitsPerReg[r]; q++) {
-
761  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
762  i++;
-
763  }
-
764  }
-
765 
-
766  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
-
767 }
-
768 
-
769 void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, int numOverrides, const char* caller) {
-
770  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
-
771 
-
772  int hasFractionExpo = 0;
-
773  int hasNegativeExpo = 0;
-
774  for (int t=0; t<numTerms; t++) {
-
775  // this is only true if exponent is precisely an integer, else pow() will NaN
-
776  if (floor(exponents[t]) != exponents[t])
-
777  hasFractionExpo = 1;
-
778  if (exponents[t] < 0)
-
779  hasNegativeExpo = 1;
-
780  }
-
781 
-
782  // ensure negative exponents are supplied along with a zero-index override
-
783  if (hasNegativeExpo) {
-
784  int hasZeroOverride = 0;
-
785  for (int v=0; v<numOverrides; v++) {
-
786  if (overrideInds[v] == 0LL) {
-
787  hasZeroOverride = 1;
-
788  break;
-
789  }
-
790  }
-
791  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
-
792  }
-
793 
-
794  // ensure fractional powers not used with negative numbers, unless overriden
-
795  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
-
796  long long int numNegInds = (1LL << (numQubits-1));
-
797 
-
798  // immediately disqualify if insufficient overrides are given to cover every negative number
-
799  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
-
800 
-
801  int allNegsOverriden;
-
802 
-
803  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
-
804  if (numQubits < 16) {
-
805 
-
806  long long int negIsOverriden[numNegInds]; // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
-
807  for (int i=0; i<numNegInds; i++)
-
808  negIsOverriden[i] = 0;
+
760  int i=0;
+
761  for (int r=0; r<numRegs; r++) {
+
762  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
763 
+
764  for (int q=0; q < numQubitsPerReg[r]; q++) {
+
765  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
+
766  i++;
+
767  }
+
768  }
+
769 
+
770  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
+
771 }
+
772 
+
773 void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, int numOverrides, const char* caller) {
+
774  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
+
775 
+
776  int hasFractionExpo = 0;
+
777  int hasNegativeExpo = 0;
+
778  for (int t=0; t<numTerms; t++) {
+
779  // this is only true if exponent is precisely an integer, else pow() will NaN
+
780  if (floor(exponents[t]) != exponents[t])
+
781  hasFractionExpo = 1;
+
782  if (exponents[t] < 0)
+
783  hasNegativeExpo = 1;
+
784  }
+
785 
+
786  // ensure negative exponents are supplied along with a zero-index override
+
787  if (hasNegativeExpo) {
+
788  int hasZeroOverride = 0;
+
789  for (int v=0; v<numOverrides; v++) {
+
790  if (overrideInds[v] == 0LL) {
+
791  hasZeroOverride = 1;
+
792  break;
+
793  }
+
794  }
+
795  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
+
796  }
+
797 
+
798  // ensure fractional powers not used with negative numbers, unless overriden
+
799  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
+
800  long long int numNegInds = (1LL << (numQubits-1));
+
801 
+
802  // immediately disqualify if insufficient overrides are given to cover every negative number
+
803  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
+
804 
+
805  int allNegsOverriden;
+
806 
+
807  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
+
808  if (numQubits < 16) {
809 
-
810  for (int v=0; v<numOverrides; v++)
-
811  if (overrideInds[v] < 0)
-
812  negIsOverriden[ -1 - overrideInds[v] ] = 1;
-
813 
-
814  allNegsOverriden = 1;
-
815  for (int i=0; i<numNegInds; i++) {
-
816  if (!negIsOverriden[i]) {
-
817  allNegsOverriden = 0;
-
818  break;
-
819  }
-
820  }
-
821  }
-
822  // otherwise, we must trust the user, else impose significant slowdowns on good users
-
823  else {
-
824  allNegsOverriden = 1;
-
825  }
-
826 
-
827  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
-
828  }
-
829 }
-
830 
-
831 void validateMultiVarPhaseFuncTerms(int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* exponents, int* numTermsPerReg, const char* caller) {
- -
833  for (int r=0; r<numRegs; r++)
-
834  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
-
835 
-
836  int numTotalTerms = 0;
-
837  for (int r=0; r<numRegs; r++)
-
838  numTotalTerms += numTermsPerReg[r];
-
839 
-
840  int hasFractionExpo = 0;
-
841  int hasNegativeExpo = 0;
-
842  for (int t=0; t<numTotalTerms; t++) {
-
843  // this is only true if exponent is precisely an integer, else pow() will NaN
-
844  if (floor(exponents[t]) != exponents[t])
-
845  hasFractionExpo = 1;
-
846  if (exponents[t] < 0)
-
847  hasNegativeExpo = 1;
-
848  }
-
849 
-
850  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
-
851 
-
852  if (encoding == TWOS_COMPLEMENT)
-
853  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
-
854 }
-
855 
-
856 
-
857 void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int* overrideInds, int numOverrides, const char* caller) {
-
858  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
859  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
810  // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
+
811  long long int negIsOverriden[32768]; // [numNegInds];
+
812  for (int i=0; i<numNegInds; i++)
+
813  negIsOverriden[i] = 0;
+
814 
+
815  for (int v=0; v<numOverrides; v++)
+
816  if (overrideInds[v] < 0)
+
817  negIsOverriden[ -1 - overrideInds[v] ] = 1;
+
818 
+
819  allNegsOverriden = 1;
+
820  for (int i=0; i<numNegInds; i++) {
+
821  if (!negIsOverriden[i]) {
+
822  allNegsOverriden = 0;
+
823  break;
+
824  }
+
825  }
+
826  }
+
827  // otherwise, we must trust the user, else impose significant slowdowns on good users
+
828  else {
+
829  allNegsOverriden = 1;
+
830  }
+
831 
+
832  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
+
833  }
+
834 }
+
835 
+
836 void validateMultiVarPhaseFuncTerms(int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* exponents, int* numTermsPerReg, const char* caller) {
+ +
838  for (int r=0; r<numRegs; r++)
+
839  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
+
840 
+
841  int numTotalTerms = 0;
+
842  for (int r=0; r<numRegs; r++)
+
843  numTotalTerms += numTermsPerReg[r];
+
844 
+
845  int hasFractionExpo = 0;
+
846  int hasNegativeExpo = 0;
+
847  for (int t=0; t<numTotalTerms; t++) {
+
848  // this is only true if exponent is precisely an integer, else pow() will NaN
+
849  if (floor(exponents[t]) != exponents[t])
+
850  hasFractionExpo = 1;
+
851  if (exponents[t] < 0)
+
852  hasNegativeExpo = 1;
+
853  }
+
854 
+
855  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
+
856 
+
857  if (encoding == TWOS_COMPLEMENT)
+
858  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
+
859 }
860 
-
861  long long int maxInd;
-
862  long long int minInd;
-
863 
-
864  if (encoding == UNSIGNED) {
-
865  minInd = 0;
-
866  maxInd = (1LL << numQubits) - 1;
-
867  for (int v=0; v<numOverrides; v++)
-
868  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
-
869  }
-
870 
-
871  if (encoding == TWOS_COMPLEMENT) {
-
872  int numValQubits = numQubits - 1; // removing sign bit
-
873  minInd = - (1LL << numValQubits);
-
874  maxInd = (1LL << numValQubits) - 1;
-
875  for (int v=0; v<numOverrides; v++)
-
876  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
-
877  }
-
878 
-
879 }
-
880 
-
881 void validateMultiVarPhaseFuncOverrides(int* numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int* overrideInds, int numOverrides, const char* caller) {
-
882  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
861 
+
862 void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int* overrideInds, int numOverrides, const char* caller) {
+
863  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
864  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
865 
+
866  long long int maxInd;
+
867  long long int minInd;
+
868 
+
869  if (encoding == UNSIGNED) {
+
870  minInd = 0;
+
871  maxInd = (1LL << numQubits) - 1;
+
872  for (int v=0; v<numOverrides; v++)
+
873  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
+
874  }
+
875 
+
876  if (encoding == TWOS_COMPLEMENT) {
+
877  int numValQubits = numQubits - 1; // removing sign bit
+
878  minInd = - (1LL << numValQubits);
+
879  maxInd = (1LL << numValQubits) - 1;
+
880  for (int v=0; v<numOverrides; v++)
+
881  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
+
882  }
883 
-
884  if (encoding == UNSIGNED) {
-
885  int i=0;
-
886  for (int v=0; v<numOverrides; v++) {
-
887  for (int r=0; r<numRegs; r++) {
-
888  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
-
889  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
-
890  i++;
-
891  }
-
892  }
-
893  }
-
894  else if (encoding == TWOS_COMPLEMENT) {
-
895  int i=0;
-
896  for (int v=0; v<numOverrides; v++) {
-
897  for (int r=0; r<numRegs; r++) {
-
898  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
-
899  long long int minInd = - (1LL << numValQubits);
-
900  long long int maxInd = (1LL << numValQubits) - 1;
-
901  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
-
902  i++;
-
903  }
-
904  }
-
905  }
-
906 }
-
907 
-
908 void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char* caller) {
-
909 
-
910  QuESTAssert(
-
911  funcCode == NORM ||
-
912  funcCode == INVERSE_NORM ||
-
913  funcCode == SCALED_NORM ||
-
914  funcCode == SCALED_INVERSE_NORM ||
-
915  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
-
916  funcCode == PRODUCT ||
-
917  funcCode == INVERSE_PRODUCT ||
-
918  funcCode == SCALED_PRODUCT ||
-
919  funcCode == SCALED_INVERSE_PRODUCT ||
-
920  funcCode == DISTANCE ||
-
921  funcCode == INVERSE_DISTANCE ||
-
922  funcCode == SCALED_DISTANCE ||
-
923  funcCode == SCALED_INVERSE_DISTANCE ||
- -
925  E_INVALID_PHASE_FUNC_NAME, caller);
-
926 
-
927  if (funcCode == NORM ||
-
928  funcCode == PRODUCT ||
-
929  funcCode == DISTANCE)
-
930  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
931 
-
932  if (funcCode == INVERSE_NORM ||
-
933  funcCode == INVERSE_PRODUCT ||
-
934  funcCode == INVERSE_DISTANCE)
-
935  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
936 
-
937  if (funcCode == SCALED_NORM ||
-
938  funcCode == SCALED_PRODUCT ||
-
939  funcCode == SCALED_DISTANCE)
+
884 }
+
885 
+
886 void validateMultiVarPhaseFuncOverrides(int* numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int* overrideInds, int numOverrides, const char* caller) {
+
887  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
888 
+
889  if (encoding == UNSIGNED) {
+
890  int i=0;
+
891  for (int v=0; v<numOverrides; v++) {
+
892  for (int r=0; r<numRegs; r++) {
+
893  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
+
894  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
+
895  i++;
+
896  }
+
897  }
+
898  }
+
899  else if (encoding == TWOS_COMPLEMENT) {
+
900  int i=0;
+
901  for (int v=0; v<numOverrides; v++) {
+
902  for (int r=0; r<numRegs; r++) {
+
903  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
+
904  long long int minInd = - (1LL << numValQubits);
+
905  long long int maxInd = (1LL << numValQubits) - 1;
+
906  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
+
907  i++;
+
908  }
+
909  }
+
910  }
+
911 }
+
912 
+
913 void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char* caller) {
+
914 
+
915  QuESTAssert(
+
916  funcCode == NORM ||
+
917  funcCode == INVERSE_NORM ||
+
918  funcCode == SCALED_NORM ||
+
919  funcCode == SCALED_INVERSE_NORM ||
+
920  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
+
921  funcCode == PRODUCT ||
+
922  funcCode == INVERSE_PRODUCT ||
+
923  funcCode == SCALED_PRODUCT ||
+
924  funcCode == SCALED_INVERSE_PRODUCT ||
+
925  funcCode == DISTANCE ||
+
926  funcCode == INVERSE_DISTANCE ||
+
927  funcCode == SCALED_DISTANCE ||
+
928  funcCode == SCALED_INVERSE_DISTANCE ||
+ +
930  E_INVALID_PHASE_FUNC_NAME, caller);
+
931 
+
932  if (funcCode == NORM ||
+
933  funcCode == PRODUCT ||
+
934  funcCode == DISTANCE)
+
935  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
936 
+
937  if (funcCode == INVERSE_NORM ||
+
938  funcCode == INVERSE_PRODUCT ||
+
939  funcCode == INVERSE_DISTANCE)
940  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
941 
-
942  if (funcCode == SCALED_INVERSE_NORM ||
-
943  funcCode == SCALED_INVERSE_PRODUCT ||
-
944  funcCode == SCALED_INVERSE_DISTANCE)
-
945  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
946 
-
947  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
-
948  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
949 
-
950  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
-
951  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
952 
-
953  if (funcCode == DISTANCE ||
-
954  funcCode == INVERSE_DISTANCE ||
-
955  funcCode == SCALED_DISTANCE ||
-
956  funcCode == SCALED_INVERSE_DISTANCE ||
- -
958  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
-
959 }
-
960 
-
961 void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char* caller) {
-
962  QuESTAssert(
-
963  encoding == UNSIGNED ||
-
964  encoding == TWOS_COMPLEMENT,
-
965  E_INVALID_BIT_ENCODING, caller);
-
966 
-
967  if (encoding == TWOS_COMPLEMENT)
-
968  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
-
969 }
-
970 
-
971 void validateMultiRegBitEncoding(int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char* caller) {
-
972  QuESTAssert(
-
973  encoding == UNSIGNED ||
-
974  encoding == TWOS_COMPLEMENT,
-
975  E_INVALID_BIT_ENCODING, caller);
-
976 
-
977  if (encoding == TWOS_COMPLEMENT)
-
978  for (int r=0; r<numRegs; r++)
-
979  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
-
980 }
+
942  if (funcCode == SCALED_NORM ||
+
943  funcCode == SCALED_PRODUCT ||
+
944  funcCode == SCALED_DISTANCE)
+
945  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
946 
+
947  if (funcCode == SCALED_INVERSE_NORM ||
+
948  funcCode == SCALED_INVERSE_PRODUCT ||
+
949  funcCode == SCALED_INVERSE_DISTANCE)
+
950  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
951 
+
952  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
+
953  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
954 
+
955  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
+
956  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
957 
+
958  if (funcCode == DISTANCE ||
+
959  funcCode == INVERSE_DISTANCE ||
+
960  funcCode == SCALED_DISTANCE ||
+
961  funcCode == SCALED_INVERSE_DISTANCE ||
+ +
963  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
+
964 }
+
965 
+
966 void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char* caller) {
+
967  QuESTAssert(
+
968  encoding == UNSIGNED ||
+
969  encoding == TWOS_COMPLEMENT,
+
970  E_INVALID_BIT_ENCODING, caller);
+
971 
+
972  if (encoding == TWOS_COMPLEMENT)
+
973  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
+
974 }
+
975 
+
976 void validateMultiRegBitEncoding(int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char* caller) {
+
977  QuESTAssert(
+
978  encoding == UNSIGNED ||
+
979  encoding == TWOS_COMPLEMENT,
+
980  E_INVALID_BIT_ENCODING, caller);
981 
-
982 #ifdef __cplusplus
-
983 }
-
984 #endif
+
982  if (encoding == TWOS_COMPLEMENT)
+
983  for (int r=0; r<numRegs; r++)
+
984  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
+
985 }
+
986 
+
987 #ifdef __cplusplus
+
988 }
+
989 #endif
@ INVERSE_PRODUCT
Definition: QuEST.h:233
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
+
void validateDensityMatrQureg(Qureg qureg, const char *caller)
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
-
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
+
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
-
void validateMeasurementProb(qreal prob, const char *caller)
+
void validateMeasurementProb(qreal prob, const char *caller)
@ E_NUM_AMPS_EXCEED_TYPE
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
@ E_MISMATCHING_PAULI_HAMIL_DIAGONAL_OP_SIZE
@ E_INVALID_QUBIT_OUTCOME
-
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
-
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
+
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
+
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
+
void validateOutcome(int outcome, const char *caller)
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
-
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
-
int isMatrix2Unitary(ComplexMatrix2 u)
+
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
+
int isMatrix2Unitary(ComplexMatrix2 u)
@ E_PAULI_HAMIL_NOT_DIAGONAL
@ PAULI_Z
Definition: QuEST.h:96
@ DISTANCE
Definition: QuEST.h:234
@ E_INVALID_NUM_PHASE_FUNC_TERMS
-
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
@ E_INVALID_PAULI_CODE
-
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
+
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
@ E_NON_UNITARY_MATRIX
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
+
void validateHamilParams(int numQubits, int numTerms, const char *caller)
@ PAULI_I
Definition: QuEST.h:96
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
-
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
+
void validateStateVecQureg(Qureg qureg, const char *caller)
+
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
@ E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC
-
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
+
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
@ E_INVALID_ELEM_INDEX
-
int isMatrix4Unitary(ComplexMatrix4 u)
-
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
+
int isMatrix4Unitary(ComplexMatrix4 u)
+
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
-
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
@ E_MISMATCHING_QUREG_TYPES
-
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
-
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
+
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
+
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
-
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
+
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
@ E_INVALID_QUBIT_INDEX
-
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
@ E_INVALID_PHASE_FUNC_NAME
-
void validateProb(qreal prob, const char *caller)
+
void validateProb(qreal prob, const char *caller)
@ E_INVALID_BIT_ENCODING
@ NORM
Definition: QuEST.h:232
-
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
+
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
@ E_NON_UNITARY_COMPLEX_PAIR
-
int isVectorUnit(qreal ux, qreal uy, qreal uz)
-
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
+
int isVectorUnit(qreal ux, qreal uy, qreal uz)
+
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
@ UNSIGNED
Definition: QuEST.h:269
@@ -1099,41 +1104,40 @@
@ E_DISTRIB_DIAG_OP_TOO_SMALL
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
@ INVERSE_DISTANCE
Definition: QuEST.h:234
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
+
void validateTwoQubitDepolProb(qreal prob, const char *caller)
@ E_SECOND_ARG_MUST_BE_STATEVEC
@ E_INVALID_CONTROL_QUBIT
-
void validateNumPauliSumTerms(int numTerms, const char *caller)
+
void validateNumPauliSumTerms(int numTerms, const char *caller)
@ E_INVALID_NUM_SUM_TERMS
@ E_DEFINED_ONLY_FOR_STATEVECS
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
+
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
+
void validateFileOpened(int opened, char *fn, const char *caller)
+
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
-
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
+
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
@ E_NEGATIVE_EXPONENT_MULTI_VAR
-
void validateControl(Qureg qureg, int controlQubit, const char *caller)
-
#define macro_isMatrixUnitary(m, dim, retVal)
+
void validateControl(Qureg qureg, int controlQubit, const char *caller)
+
#define macro_isMatrixUnitary(m, dim, retVal)
@ PAULI_X
Definition: QuEST.h:96
-
int isComplexUnit(Complex alpha)
+
int isComplexUnit(Complex alpha)
@ E_INVALID_PROB
-
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
-
int isMatrixNUnitary(ComplexMatrixN u)
+
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
+
int isMatrixNUnitary(ComplexMatrixN u)
@ E_QUBITS_NOT_UNIQUE
-
void validateVector(Vector vec, const char *caller)
+
void validateVector(Vector vec, const char *caller)
@ E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX
-
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
+
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
@ E_CONTROL_TARGET_COLLISION
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
+
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
@ E_DEFINED_ONLY_FOR_DENSMATRS
@ E_INVALID_KRAUS_OPS
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
@ E_INVALID_STATE_INDEX
-
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
-
void exitWithError(const char *msg, const char *func)
-
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
+
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
+
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
-
int areUniqueQubits(int *qubits, int numQubits)
+
int areUniqueQubits(int *qubits, int numQubits)
@ E_TARGET_IN_CONTROLS
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
@ E_INVALID_NUM_QUBITS
@@ -1142,17 +1146,17 @@
@ E_INVALID_PAULI_HAMIL_PARAMS
@ E_INVALID_UNITARY_SIZE
@ E_INVALID_ONE_QUBIT_PAULI_PROBS
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
+
void validateOneQubitDephaseProb(qreal prob, const char *caller)
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
-
void validateControlState(int *controlState, int numControlQubits, const char *caller)
+
void validateControlState(int *controlState, int numControlQubits, const char *caller)
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
int isValidPauliCode(enum pauliOpType code)
+
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
+
int isValidPauliCode(enum pauliOpType code)
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
@ E_INVALID_TARGET_QUBIT
@ E_COMPLEX_MATRIX_NOT_INIT
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
+
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
@ E_CANNOT_OPEN_FILE
@ E_DISTRIB_QUREG_TOO_SMALL
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
@@ -1163,52 +1167,52 @@
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
@ PAULI_Y
Definition: QuEST.h:96
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
-
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
+
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
@ E_INVALID_AMP_INDEX
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
+
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
qreal ** real
Definition: QuEST.h:189
-
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
+
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
@ E_INVALID_NUM_RANKS
@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
static const char * errorMessages[]
-
void QuESTAssert(int isValid, ErrorCode code, const char *func)
-
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
+
void QuESTAssert(int isValid, ErrorCode code, const char *func)
+
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
@ E_INVALID_NUM_AMPS
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
+
void validateOneQubitDepolProb(qreal prob, const char *caller)
@ E_COLLAPSE_STATE_ZERO_PROB
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
+
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
@ E_TARGETS_NOT_UNIQUE
@ INVERSE_NORM
Definition: QuEST.h:232
Represents a system of qubits.
Definition: QuEST.h:322
-
void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
-
void validateNumQubitsInMatrix(int numQubits, const char *caller)
+
void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
+
void validateNumQubitsInMatrix(int numQubits, const char *caller)
qreal ** imag
Definition: QuEST.h:190
-
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
+
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
@ E_MISMATCHING_QUREG_DIMENSIONS
ErrorCode
@ E_INVALID_TROTTER_REPS
@ E_INVALID_NUM_CONTROLS
@ PRODUCT
Definition: QuEST.h:233
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
+
void validatePauliHamil(PauliHamil hamil, const char *caller)
-
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
+
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
char errMsgBuffer[1024]
@ E_INVALID_NUM_CREATE_QUBITS
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
+
void validateDiagOpInit(DiagonalOp op, const char *caller)
@ E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS
-
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
+
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
-
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
+
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
int numQubits
Definition: QuEST.h:188
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
+
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
-
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
-
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
+
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
+
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
-
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
+
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
@ E_UNNORM_PROBS
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
@@ -1217,45 +1221,46 @@
@ E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
-
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
+
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
@ E_FRACTIONAL_EXPONENT_MULTI_VAR
qreal real
Definition: QuEST.h:105
-
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
+
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
@ E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1399
-
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
+
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1414
+
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
qreal imag
Definition: QuEST.h:106
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
+
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
@ E_INVALID_NUM_ELEMS
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
+
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
+
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
@ E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE
@ E_INVALID_NUM_TARGETS
@ E_SYS_TOO_BIG_TO_PRINT
-
void validateNumRanks(int numRanks, const char *caller)
+
void validateNumRanks(int numRanks, const char *caller)
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
Represents one complex number.
Definition: QuEST.h:103
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
void validateTrotterParams(int order, int reps, const char *caller)
-
int isComplexPairUnitary(Complex alpha, Complex beta)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
+
void validateTrotterParams(int order, int reps, const char *caller)
+
int isComplexPairUnitary(Complex alpha, Complex beta)
+
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
@ E_DIAGONAL_OP_NOT_INITIALISED
-
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
+
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
-
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
+
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
@ E_SUCCESS
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
+
void validateOneQubitDampingProb(qreal prob, const char *caller)
@ E_ZERO_VECTOR
+
void default_invalidQuESTInputError(const char *errMsg, const char *errFunc)
@ E_CONTROLS_NOT_UNIQUE
@ E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
+
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
+
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
+
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
diff --git a/docs/QuEST__validation_8h.html b/docs/QuEST__validation_8h.html index 85ef871e8..403d513f0 100644 --- a/docs/QuEST__validation_8h.html +++ b/docs/QuEST__validation_8h.html @@ -27,7 +27,7 @@ @@ -242,15 +242,15 @@

-

Definition at line 378 of file QuEST_validation.c.

-
378  {
-
379  long long int indMax = 1LL << qureg.numQubitsRepresented;
-
380  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
-
381 }
+

Definition at line 382 of file QuEST_validation.c.

+
382  {
+
383  long long int indMax = 1LL << qureg.numQubitsRepresented;
+
384  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
+
385 }
-

References E_INVALID_AMP_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_AMP_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by getAmp(), getDensityAmp(), getImagAmp(), getProbAmp(), getRealAmp(), and validateNumAmps().

+

Referenced by getAmp(), getDensityAmp(), getImagAmp(), getProbAmp(), getRealAmp(), and validateNumAmps().

@@ -286,20 +286,20 @@

-

Definition at line 961 of file QuEST_validation.c.

-
961  {
-
962  QuESTAssert(
-
963  encoding == UNSIGNED ||
-
964  encoding == TWOS_COMPLEMENT,
-
965  E_INVALID_BIT_ENCODING, caller);
-
966 
-
967  if (encoding == TWOS_COMPLEMENT)
-
968  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
-
969 }
+

Definition at line 966 of file QuEST_validation.c.

+
966  {
+
967  QuESTAssert(
+
968  encoding == UNSIGNED ||
+
969  encoding == TWOS_COMPLEMENT,
+
970  E_INVALID_BIT_ENCODING, caller);
+
971 
+
972  if (encoding == TWOS_COMPLEMENT)
+
973  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
+
974 }
-

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -335,15 +335,15 @@

-

Definition at line 464 of file QuEST_validation.c.

-
464  {
-
465  for (int i=0; i < numControlQubits; i++)
-
466  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
-
467 }
+

Definition at line 468 of file QuEST_validation.c.

+
468  {
+
469  for (int i=0; i < numControlQubits; i++)
+
470  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
+
471 }
-

References E_INVALID_CONTROLS_BIT_STATE, and QuESTAssert().

+

References E_INVALID_CONTROLS_BIT_STATE, and QuESTAssert().

-

Referenced by multiStateControlledUnitary().

+

Referenced by multiStateControlledUnitary().

@@ -385,16 +385,16 @@

-

Definition at line 404 of file QuEST_validation.c.

- @@ -424,14 +424,14 @@

-

Definition at line 515 of file QuEST_validation.c.

- @@ -467,15 +467,15 @@

-

Definition at line 709 of file QuEST_validation.c.

- @@ -505,14 +505,14 @@

-

Definition at line 705 of file QuEST_validation.c.

- @@ -548,19 +548,19 @@

-

Definition at line 714 of file QuEST_validation.c.

- @@ -596,40 +596,40 @@

-

Definition at line 723 of file QuEST_validation.c.

-
723  {
-
724  // hamil itself already validated as general Pauli Hamiltonian
-
725 
-
726  // destroy hamil before raising exceptions if validation fails
-
727  int isValid;
-
728 
-
729  // mustn't be more elements than can fit in the type
-
730  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
731  isValid = hamil.numQubits <= maxQubits;
-
732  if (!isValid)
-
733  destroyPauliHamil(hamil);
-
734  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
-
735 
-
736  // must be at least one amplitude per node
-
737  long unsigned int numElems = (1UL<<hamil.numQubits);
-
738  isValid = numElems >= numRanks;
-
739  if (!isValid)
-
740  destroyPauliHamil(hamil);
-
741  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
742 
-
743  // must contain only I and Z
-
744  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
-
745  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
-
746  if (!isValid)
-
747  destroyPauliHamil(hamil);
-
748 
-
749  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
-
750  }
-
751 }
+

Definition at line 727 of file QuEST_validation.c.

+
727  {
+
728  // hamil itself already validated as general Pauli Hamiltonian
+
729 
+
730  // destroy hamil before raising exceptions if validation fails
+
731  int isValid;
+
732 
+
733  // mustn't be more elements than can fit in the type
+
734  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
735  isValid = hamil.numQubits <= maxQubits;
+
736  if (!isValid)
+
737  destroyPauliHamil(hamil);
+
738  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
+
739 
+
740  // must be at least one amplitude per node
+
741  long unsigned int numElems = (1UL<<hamil.numQubits);
+
742  isValid = numElems >= numRanks;
+
743  if (!isValid)
+
744  destroyPauliHamil(hamil);
+
745  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
+
746 
+
747  // must contain only I and Z
+
748  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
+
749  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
+
750  if (!isValid)
+
751  destroyPauliHamil(hamil);
+
752 
+
753  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
+
754  }
+
755 }
-

References calcLog2(), destroyPauliHamil(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_NUM_AMPS_EXCEED_TYPE, E_PAULI_HAMIL_NOT_DIAGONAL, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_Z, PauliHamil::pauliCodes, and QuESTAssert().

+

References calcLog2(), destroyPauliHamil(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_NUM_AMPS_EXCEED_TYPE, E_PAULI_HAMIL_NOT_DIAGONAL, PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_Z, PauliHamil::pauliCodes, and QuESTAssert().

-

Referenced by createDiagonalOpFromPauliHamilFile().

+

Referenced by createDiagonalOpFromPauliHamilFile().

@@ -665,18 +665,18 @@

-

Definition at line 539 of file QuEST_validation.c.

-
539  {
-
540  if (!opened) {
-
541 
- - -
544  }
-
545 }
+

Definition at line 543 of file QuEST_validation.c.

+
543  {
+
544  if (!opened) {
+
545 
+ + +
548  }
+
549 }
-

References E_CANNOT_OPEN_FILE, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References E_CANNOT_OPEN_FILE, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile(), initStateFromSingleFile(), and writeRecordedQASMToFile().

+

Referenced by createPauliHamilFromFile(), initStateFromSingleFile(), and writeRecordedQASMToFile().

@@ -724,20 +724,20 @@

-

Definition at line 669 of file QuEST_validation.c.

-
669  {
-
670  if (!parsed) {
- -
672  fclose(file);
-
673 
- - -
676  }
-
677 }
+

Definition at line 673 of file QuEST_validation.c.

+
673  {
+
674  if (!parsed) {
+ +
676  fclose(file);
+
677 
+ + +
680  }
+
681 }
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -785,19 +785,19 @@

-

Definition at line 660 of file QuEST_validation.c.

-
660  {
-
661  if (!(numQubits > 0 && numTerms > 0)) {
-
662  fclose(file);
-
663 
- - -
666  }
-
667 }
+

Definition at line 664 of file QuEST_validation.c.

+
664  {
+
665  if (!(numQubits > 0 && numTerms > 0)) {
+
666  fclose(file);
+
667 
+ + +
670  }
+
671 }
-

References E_INVALID_PAULI_HAMIL_FILE_PARAMS, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References E_INVALID_PAULI_HAMIL_FILE_PARAMS, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -845,20 +845,20 @@

-

Definition at line 689 of file QuEST_validation.c.

-
689  {
-
690  if (!isValidPauliCode(code)) {
- -
692  fclose(file);
-
693 
- - -
696  }
-
697 }
+

Definition at line 693 of file QuEST_validation.c.

+
693  {
+
694  if (!isValidPauliCode(code)) {
+ +
696  fclose(file);
+
697 
+ + +
700  }
+
701 }
-

References destroyPauliHamil(), E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, errMsgBuffer, errorMessages, invalidQuESTInputError(), and isValidPauliCode().

+

References destroyPauliHamil(), E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE, errMsgBuffer, errorMessages, invalidQuESTInputError(), and isValidPauliCode().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -906,20 +906,20 @@

-

Definition at line 679 of file QuEST_validation.c.

-
679  {
-
680  if (!parsed) {
- -
682  fclose(file);
-
683 
- - -
686  }
-
687 }
+

Definition at line 683 of file QuEST_validation.c.

+
683  {
+
684  if (!parsed) {
+ +
686  fclose(file);
+
687 
+ + +
690  }
+
691 }
-

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, errMsgBuffer, errorMessages, and invalidQuESTInputError().

+

References destroyPauliHamil(), E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI, errMsgBuffer, errorMessages, and invalidQuESTInputError().

-

Referenced by createPauliHamilFromFile().

+

Referenced by createPauliHamilFromFile().

@@ -955,14 +955,14 @@

-

Definition at line 647 of file QuEST_validation.c.

-
647  {
-
648  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
-
649 }
+

Definition at line 651 of file QuEST_validation.c.

+
651  {
+
652  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
+
653 }
-

References E_INVALID_PAULI_HAMIL_PARAMS, and QuESTAssert().

+

References E_INVALID_PAULI_HAMIL_PARAMS, and QuESTAssert().

-

Referenced by createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), and validatePauliHamil().

+

Referenced by createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), and validatePauliHamil().

@@ -998,14 +998,14 @@

-

Definition at line 527 of file QuEST_validation.c.

- @@ -1041,14 +1041,14 @@

-

Definition at line 656 of file QuEST_validation.c.

- @@ -1084,14 +1084,14 @@

-

Definition at line 531 of file QuEST_validation.c.

- @@ -1121,20 +1121,20 @@

-

Definition at line 482 of file QuEST_validation.c.

-
482  {
-
483 
-
484  /* note that for (most) compilers which don't automatically initialise
-
485  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
-
486  * succeeded. It can not be used to differentiate whether a user actually attempted
-
487  * to initialise or create their ComplexMatrixN instance.
-
488  */
-
489  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
-
490 }
+

Definition at line 486 of file QuEST_validation.c.

+
486  {
+
487 
+
488  /* note that for (most) compilers which don't automatically initialise
+
489  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
+
490  * succeeded. It can not be used to differentiate whether a user actually attempted
+
491  * to initialise or create their ComplexMatrixN instance.
+
492  */
+
493  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
+
494 }
-

References E_COMPLEX_MATRIX_NOT_INIT, ComplexMatrixN::imag, QuESTAssert(), and ComplexMatrixN::real.

+

References E_COMPLEX_MATRIX_NOT_INIT, ComplexMatrixN::imag, QuESTAssert(), and ComplexMatrixN::real.

-

Referenced by createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), validateMultiQubitKrausMap(), and validateMultiQubitMatrix().

+

Referenced by createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), validateMultiQubitKrausMap(), and validateMultiQubitMatrix().

@@ -1164,14 +1164,14 @@

-

Definition at line 523 of file QuEST_validation.c.

-
523  {
-
524  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
-
525 }
+

Definition at line 527 of file QuEST_validation.c.

+
527  {
+
528  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
+
529 }
-

References E_COLLAPSE_STATE_ZERO_PROB, and QuESTAssert().

+

References E_COLLAPSE_STATE_ZERO_PROB, and QuESTAssert().

-

Referenced by collapseToOutcome().

+

Referenced by collapseToOutcome().

@@ -1213,18 +1213,18 @@

-

Definition at line 432 of file QuEST_validation.c.

-
432  {
-
433  validateNumControls(qureg, numControlQubits, caller);
-
434  for (int i=0; i < numControlQubits; i++)
-
435  validateControl(qureg, controlQubits[i], caller);
-
436 
-
437  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
-
438 }
+

Definition at line 436 of file QuEST_validation.c.

+
436  {
+
437  validateNumControls(qureg, numControlQubits, caller);
+
438  for (int i=0; i < numControlQubits; i++)
+
439  validateControl(qureg, controlQubits[i], caller);
+
440 
+
441  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
+
442 }
-

References areUniqueQubits(), E_CONTROLS_NOT_UNIQUE, QuESTAssert(), validateControl(), and validateNumControls().

+

References areUniqueQubits(), E_CONTROLS_NOT_UNIQUE, QuESTAssert(), validateControl(), and validateNumControls().

-

Referenced by validateMultiControlsMultiTargets(), and validateMultiControlsTarget().

+

Referenced by validateMultiControlsMultiTargets(), and validateMultiControlsTarget().

@@ -1278,19 +1278,19 @@

-

Definition at line 455 of file QuEST_validation.c.

-
455  {
-
456  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
457  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
-
458  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
-
459  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
-
460  int overlap = ctrlMask & targMask;
-
461  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
-
462 }
+

Definition at line 459 of file QuEST_validation.c.

+
459  {
+
460  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
+
461  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
+
462  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
+
463  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
+
464  int overlap = ctrlMask & targMask;
+
465  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
+
466 }
-

References E_CONTROL_TARGET_COLLISION, getQubitBitMask(), QuESTAssert(), validateMultiControls(), and validateMultiTargets().

+

References E_CONTROL_TARGET_COLLISION, getQubitBitMask(), QuESTAssert(), validateMultiControls(), and validateMultiTargets().

-

Referenced by applyMultiControlledMatrixN(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), and multiControlledTwoQubitUnitary().

+

Referenced by applyMultiControlledMatrixN(), controlledMultiQubitUnitary(), controlledTwoQubitUnitary(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), and multiControlledTwoQubitUnitary().

@@ -1338,17 +1338,17 @@

-

Definition at line 448 of file QuEST_validation.c.

-
448  {
-
449  validateTarget(qureg, targetQubit, caller);
-
450  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
-
451  for (int i=0; i < numControlQubits; i++)
-
452  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
-
453 }
+

Definition at line 452 of file QuEST_validation.c.

+
452  {
+
453  validateTarget(qureg, targetQubit, caller);
+
454  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
+
455  for (int i=0; i < numControlQubits; i++)
+
456  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
+
457 }
-

References E_TARGET_IN_CONTROLS, QuESTAssert(), validateMultiControls(), and validateTarget().

+

References E_TARGET_IN_CONTROLS, QuESTAssert(), validateMultiControls(), and validateTarget().

-

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

+

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

@@ -1396,27 +1396,27 @@

-

Definition at line 630 of file QuEST_validation.c.

-
630  {
-
631  int opNumQubits = numTargs;
-
632  int superOpNumQubits = 2*opNumQubits;
-
633  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
634  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
-
635 
-
636  for (int n=0; n<numOps; n++) {
-
637  validateMatrixInit(ops[n], __func__);
-
638  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
-
639  }
-
640 
-
641  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
642 
-
643  int isPos = isCompletelyPositiveMapN(ops, numOps);
-
644  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
645 }
+

Definition at line 634 of file QuEST_validation.c.

+
634  {
+
635  int opNumQubits = numTargs;
+
636  int superOpNumQubits = 2*opNumQubits;
+
637  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
638  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
+
639 
+
640  for (int n=0; n<numOps; n++) {
+
641  validateMatrixInit(ops[n], __func__);
+
642  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
+
643  }
+
644 
+
645  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
646 
+
647  int isPos = isCompletelyPositiveMapN(ops, numOps);
+
648  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
649 }
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, isCompletelyPositiveMapN(), QuESTAssert(), validateMatrixInit(), and validateMultiQubitMatrixFitsInNode().

+

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, isCompletelyPositiveMapN(), QuESTAssert(), validateMatrixInit(), and validateMultiQubitMatrixFitsInNode().

-

Referenced by mixMultiQubitKrausMap().

+

Referenced by mixMultiQubitKrausMap().

@@ -1458,16 +1458,16 @@

-

Definition at line 492 of file QuEST_validation.c.

- @@ -1503,14 +1503,14 @@

-

Definition at line 469 of file QuEST_validation.c.

- @@ -1552,18 +1552,18 @@

-

Definition at line 440 of file QuEST_validation.c.

-
440  {
-
441  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
-
442  for (int i=0; i < numQubits; i++)
-
443  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
444 
-
445  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
-
446 }
+

Definition at line 444 of file QuEST_validation.c.

+
444  {
+
445  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
446  for (int i=0; i < numQubits; i++)
+
447  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
+
448 
+
449  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
+
450 }
-

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, Qureg::numQubitsRepresented, and QuESTAssert().

+

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), multiControlledPhaseFlip(), and multiControlledPhaseShift().

+

Referenced by applyPhaseFunc(), applyPhaseFuncOverrides(), multiControlledPhaseFlip(), and multiControlledPhaseShift().

@@ -1605,15 +1605,15 @@

-

Definition at line 498 of file QuEST_validation.c.

- @@ -1655,21 +1655,21 @@

-

Definition at line 971 of file QuEST_validation.c.

-
971  {
-
972  QuESTAssert(
-
973  encoding == UNSIGNED ||
-
974  encoding == TWOS_COMPLEMENT,
-
975  E_INVALID_BIT_ENCODING, caller);
-
976 
-
977  if (encoding == TWOS_COMPLEMENT)
-
978  for (int r=0; r<numRegs; r++)
-
979  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
-
980 }
+

Definition at line 976 of file QuEST_validation.c.

+
976  {
+
977  QuESTAssert(
+
978  encoding == UNSIGNED ||
+
979  encoding == TWOS_COMPLEMENT,
+
980  E_INVALID_BIT_ENCODING, caller);
+
981 
+
982  if (encoding == TWOS_COMPLEMENT)
+
983  for (int r=0; r<numRegs; r++)
+
984  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
+
985 }
-

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_BIT_ENCODING, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -1711,18 +1711,18 @@

-

Definition at line 424 of file QuEST_validation.c.

-
424  {
-
425  validateNumTargets(qureg, numTargetQubits, caller);
-
426  for (int i=0; i < numTargetQubits; i++)
-
427  validateTarget(qureg, targetQubits[i], caller);
-
428 
-
429  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
-
430 }
+

Definition at line 428 of file QuEST_validation.c.

+
428  {
+
429  validateNumTargets(qureg, numTargetQubits, caller);
+
430  for (int i=0; i < numTargetQubits; i++)
+
431  validateTarget(qureg, targetQubits[i], caller);
+
432 
+
433  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
+
434 }
-

References areUniqueQubits(), E_TARGETS_NOT_UNIQUE, QuESTAssert(), validateNumTargets(), and validateTarget().

+

References areUniqueQubits(), E_TARGETS_NOT_UNIQUE, QuESTAssert(), validateNumTargets(), and validateTarget().

-

Referenced by applyMatrix4(), applyMatrixN(), applyQFT(), calcExpecPauliProd(), calcProbOfAllOutcomes(), mixMultiQubitKrausMap(), mixTwoQubitKrausMap(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), twoQubitUnitary(), and validateMultiControlsMultiTargets().

+

Referenced by applyMatrix4(), applyMatrixN(), applyQFT(), calcExpecPauliProd(), calcProbOfAllOutcomes(), mixMultiQubitKrausMap(), mixTwoQubitKrausMap(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), twoQubitUnitary(), and validateMultiControlsMultiTargets().

@@ -1776,37 +1776,37 @@

-

Definition at line 881 of file QuEST_validation.c.

-
881  {
-
882  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
883 
-
884  if (encoding == UNSIGNED) {
-
885  int i=0;
-
886  for (int v=0; v<numOverrides; v++) {
-
887  for (int r=0; r<numRegs; r++) {
-
888  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
-
889  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
-
890  i++;
-
891  }
-
892  }
-
893  }
-
894  else if (encoding == TWOS_COMPLEMENT) {
-
895  int i=0;
-
896  for (int v=0; v<numOverrides; v++) {
-
897  for (int r=0; r<numRegs; r++) {
-
898  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
-
899  long long int minInd = - (1LL << numValQubits);
-
900  long long int maxInd = (1LL << numValQubits) - 1;
-
901  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
-
902  i++;
-
903  }
-
904  }
-
905  }
-
906 }
-
-

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

- -

Referenced by applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFuncOverrides(), and applyParamNamedPhaseFuncOverrides().

+

Definition at line 886 of file QuEST_validation.c.

+
886  {
+
887  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
888 
+
889  if (encoding == UNSIGNED) {
+
890  int i=0;
+
891  for (int v=0; v<numOverrides; v++) {
+
892  for (int r=0; r<numRegs; r++) {
+
893  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
+
894  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
+
895  i++;
+
896  }
+
897  }
+
898  }
+
899  else if (encoding == TWOS_COMPLEMENT) {
+
900  int i=0;
+
901  for (int v=0; v<numOverrides; v++) {
+
902  for (int r=0; r<numRegs; r++) {
+
903  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
+
904  long long int minInd = - (1LL << numValQubits);
+
905  long long int maxInd = (1LL << numValQubits) - 1;
+
906  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
+
907  i++;
+
908  }
+
909  }
+
910  }
+
911 }
+
+

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+ +

Referenced by applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFuncOverrides(), and applyParamNamedPhaseFuncOverrides().

@@ -1860,35 +1860,35 @@

-

Definition at line 831 of file QuEST_validation.c.

-
831  {
- -
833  for (int r=0; r<numRegs; r++)
-
834  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
-
835 
-
836  int numTotalTerms = 0;
-
837  for (int r=0; r<numRegs; r++)
-
838  numTotalTerms += numTermsPerReg[r];
-
839 
-
840  int hasFractionExpo = 0;
-
841  int hasNegativeExpo = 0;
-
842  for (int t=0; t<numTotalTerms; t++) {
-
843  // this is only true if exponent is precisely an integer, else pow() will NaN
-
844  if (floor(exponents[t]) != exponents[t])
-
845  hasFractionExpo = 1;
-
846  if (exponents[t] < 0)
-
847  hasNegativeExpo = 1;
-
848  }
-
849 
-
850  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
-
851 
-
852  if (encoding == TWOS_COMPLEMENT)
-
853  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
-
854 }
+

Definition at line 836 of file QuEST_validation.c.

+
836  {
+ +
838  for (int r=0; r<numRegs; r++)
+
839  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
+
840 
+
841  int numTotalTerms = 0;
+
842  for (int r=0; r<numRegs; r++)
+
843  numTotalTerms += numTermsPerReg[r];
+
844 
+
845  int hasFractionExpo = 0;
+
846  int hasNegativeExpo = 0;
+
847  for (int t=0; t<numTotalTerms; t++) {
+
848  // this is only true if exponent is precisely an integer, else pow() will NaN
+
849  if (floor(exponents[t]) != exponents[t])
+
850  hasFractionExpo = 1;
+
851  if (exponents[t] < 0)
+
852  hasNegativeExpo = 1;
+
853  }
+
854 
+
855  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
+
856 
+
857  if (encoding == TWOS_COMPLEMENT)
+
858  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
+
859 }
-

References E_FRACTIONAL_EXPONENT_MULTI_VAR, E_INVALID_NUM_PHASE_FUNC_TERMS, E_INVALID_NUM_SUBREGISTERS, E_NEGATIVE_EXPONENT_MULTI_VAR, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, QuESTAssert(), and TWOS_COMPLEMENT.

+

References E_FRACTIONAL_EXPONENT_MULTI_VAR, E_INVALID_NUM_PHASE_FUNC_TERMS, E_INVALID_NUM_SUBREGISTERS, E_NEGATIVE_EXPONENT_MULTI_VAR, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, QuESTAssert(), and TWOS_COMPLEMENT.

-

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), and applyMultiVarPhaseFuncOverrides().

@@ -1924,16 +1924,16 @@

-

Definition at line 551 of file QuEST_validation.c.

-
551  {
-
552  validateProb(prob1, caller);
-
553  validateProb(prob2, caller);
-
554 
-
555  qreal sum = prob1 + prob2;
-
556  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
-
557 }
+

Definition at line 555 of file QuEST_validation.c.

+
555  {
+
556  validateProb(prob1, caller);
+
557  validateProb(prob2, caller);
+
558 
+
559  qreal sum = prob1 + prob2;
+
560  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
+
561 }
-

References E_UNNORM_PROBS, qreal, QuESTAssert(), and validateProb().

+

References E_UNNORM_PROBS, qreal, QuESTAssert(), and validateProb().

@@ -1975,16 +1975,16 @@

-

Definition at line 383 of file QuEST_validation.c.

-
383  {
-
384  validateAmpIndex(qureg, startInd, caller);
-
385  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
-
386  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
-
387 }
+

Definition at line 387 of file QuEST_validation.c.

+
387  {
+
388  validateAmpIndex(qureg, startInd, caller);
+
389  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
+
390  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
+
391 }
-

References E_INVALID_NUM_AMPS, E_INVALID_OFFSET_NUM_AMPS_QUREG, Qureg::numAmpsTotal, QuESTAssert(), and validateAmpIndex().

+

References E_INVALID_NUM_AMPS, E_INVALID_OFFSET_NUM_AMPS_QUREG, Qureg::numAmpsTotal, QuESTAssert(), and validateAmpIndex().

-

Referenced by setAmps().

+

Referenced by setAmps().

@@ -2026,17 +2026,17 @@

-

Definition at line 389 of file QuEST_validation.c.

-
389  {
-
390  long long int indMax = 1LL << op.numQubits;
-
391  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
-
392  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
-
393  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
-
394 }
+

Definition at line 393 of file QuEST_validation.c.

+
393  {
+
394  long long int indMax = 1LL << op.numQubits;
+
395  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
+
396  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
+
397  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
+
398 }
-

References E_INVALID_ELEM_INDEX, E_INVALID_NUM_ELEMS, E_INVALID_OFFSET_NUM_ELEMS_DIAG, DiagonalOp::numQubits, and QuESTAssert().

+

References E_INVALID_ELEM_INDEX, E_INVALID_NUM_ELEMS, E_INVALID_OFFSET_NUM_ELEMS_DIAG, DiagonalOp::numQubits, and QuESTAssert().

-

Referenced by setDiagonalOpElems().

+

Referenced by setDiagonalOpElems().

@@ -2066,14 +2066,14 @@

-

Definition at line 602 of file QuEST_validation.c.

-
602  {
-
603  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
-
604 }
+

Definition at line 606 of file QuEST_validation.c.

+
606  {
+
607  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
+
608 }
-

References E_INVALID_NUM_SUM_TERMS, and QuESTAssert().

+

References E_INVALID_NUM_SUM_TERMS, and QuESTAssert().

-

Referenced by applyPauliSum(), and calcExpecPauliSum().

+

Referenced by applyPauliSum(), and calcExpecPauliSum().

@@ -2109,22 +2109,22 @@

-

Definition at line 361 of file QuEST_validation.c.

-
361  {
-
362  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
363 
-
364  // mustn't be more amplitudes than can fit in the type
-
365  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
366  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+

Definition at line 365 of file QuEST_validation.c.

+
365  {
+
366  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
367 
-
368  // must be at least one amplitude per node
-
369  long unsigned int numAmps = (1UL<<numQubits);
-
370  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
-
371 }
+
368  // mustn't be more amplitudes than can fit in the type
+
369  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
370  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
371 
+
372  // must be at least one amplitude per node
+
373  long unsigned int numAmps = (1UL<<numQubits);
+
374  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
+
375 }
-

References calcLog2(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

+

References calcLog2(), E_DISTRIB_DIAG_OP_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

-

Referenced by createDiagonalOp().

+

Referenced by createDiagonalOp().

@@ -2154,14 +2154,14 @@

-

Definition at line 357 of file QuEST_validation.c.

-
357  {
-
358  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
-
359 }
+

Definition at line 361 of file QuEST_validation.c.

+
361  {
+
362  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
+
363 }
-

References E_INVALID_NUM_QUBITS, and QuESTAssert().

+

References E_INVALID_NUM_QUBITS, and QuESTAssert().

-

Referenced by createComplexMatrixN().

+

Referenced by createComplexMatrixN().

@@ -2197,20 +2197,20 @@

-

Definition at line 345 of file QuEST_validation.c.

-
345  {
-
346  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
-
347 
-
348  // mustn't be more amplitudes than can fit in the type
-
349  unsigned int maxQubits = calcLog2(SIZE_MAX);
-
350  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+

Definition at line 349 of file QuEST_validation.c.

+
349  {
+
350  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
351 
-
352  // must be at least one amplitude per node
-
353  long unsigned int numAmps = (1UL<<numQubits);
-
354  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
-
355 }
+
352  // mustn't be more amplitudes than can fit in the type
+
353  unsigned int maxQubits = calcLog2(SIZE_MAX);
+
354  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
+
355 
+
356  // must be at least one amplitude per node
+
357  long unsigned int numAmps = (1UL<<numQubits);
+
358  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
+
359 }
-

References calcLog2(), E_DISTRIB_QUREG_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

+

References calcLog2(), E_DISTRIB_QUREG_TOO_SMALL, E_INVALID_NUM_CREATE_QUBITS, E_NUM_AMPS_EXCEED_TYPE, and QuESTAssert().

Referenced by createDensityQureg(), and createQureg().

@@ -2242,22 +2242,22 @@

-

Definition at line 331 of file QuEST_validation.c.

-
331  {
-
332 
-
333  /* silly but robust way to determine if numRanks is a power of 2,
-
334  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
-
335  * system / precsision dependent
-
336  */
-
337  int isValid = 0;
-
338  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
-
339  if (exp2 == numRanks)
-
340  isValid = 1;
-
341 
-
342  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
-
343 }
+

Definition at line 335 of file QuEST_validation.c.

+
335  {
+
336 
+
337  /* silly but robust way to determine if numRanks is a power of 2,
+
338  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
+
339  * system / precsision dependent
+
340  */
+
341  int isValid = 0;
+
342  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
+
343  if (exp2 == numRanks)
+
344  isValid = 1;
+
345 
+
346  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
+
347 }
-

References E_INVALID_NUM_RANKS, and QuESTAssert().

+

References E_INVALID_NUM_RANKS, and QuESTAssert().

Referenced by createQuESTEnv().

@@ -2289,15 +2289,15 @@

-

Definition at line 574 of file QuEST_validation.c.

-
574  {
-
575  validateProb(prob, caller);
-
576  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
577 }
+

Definition at line 578 of file QuEST_validation.c.

+
578  {
+
579  validateProb(prob, caller);
+
580  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
+
581 }
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixDamping().

+

Referenced by mixDamping().

@@ -2327,15 +2327,15 @@

-

Definition at line 559 of file QuEST_validation.c.

-
559  {
-
560  validateProb(prob, caller);
-
561  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
-
562 }
+

Definition at line 563 of file QuEST_validation.c.

+
563  {
+
564  validateProb(prob, caller);
+
565  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
+
566 }
-

References E_INVALID_ONE_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixDephasing().

+

Referenced by mixDephasing().

@@ -2365,15 +2365,15 @@

-

Definition at line 569 of file QuEST_validation.c.

-
569  {
-
570  validateProb(prob, caller);
-
571  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
-
572 }
+

Definition at line 573 of file QuEST_validation.c.

+
573  {
+
574  validateProb(prob, caller);
+
575  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
+
576 }
-

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixDepolarising().

+

Referenced by mixDepolarising().

@@ -2415,22 +2415,22 @@

-

Definition at line 606 of file QuEST_validation.c.

-
606  {
-
607  int opNumQubits = 1;
-
608  int superOpNumQubits = 2*opNumQubits;
-
609  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
610  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
-
611 
-
612  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
613 
-
614  int isPos = isCompletelyPositiveMap2(ops, numOps);
-
615  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
616 }
+

Definition at line 610 of file QuEST_validation.c.

+
610  {
+
611  int opNumQubits = 1;
+
612  int superOpNumQubits = 2*opNumQubits;
+
613  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
614  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
+
615 
+
616  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
617 
+
618  int isPos = isCompletelyPositiveMap2(ops, numOps);
+
619  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
620 }
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, isCompletelyPositiveMap2(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

+

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, isCompletelyPositiveMap2(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

-

Referenced by mixKrausMap().

+

Referenced by mixKrausMap().

@@ -2472,21 +2472,21 @@

-

Definition at line 584 of file QuEST_validation.c.

-
584  {
-
585  validateProb(probX, caller);
-
586  validateProb(probY, caller);
-
587  validateProb(probZ, caller);
-
588 
-
589  qreal probNoError = 1 - probX - probY - probZ;
-
590  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
591  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
592  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
-
593 }
+

Definition at line 588 of file QuEST_validation.c.

+
588  {
+
589  validateProb(probX, caller);
+
590  validateProb(probY, caller);
+
591  validateProb(probZ, caller);
+
592 
+
593  qreal probNoError = 1 - probX - probY - probZ;
+
594  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
595  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
596  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
+
597 }
-

References E_INVALID_ONE_QUBIT_PAULI_PROBS, qreal, QuESTAssert(), and validateProb().

+

References E_INVALID_ONE_QUBIT_PAULI_PROBS, qreal, QuESTAssert(), and validateProb().

-

Referenced by mixPauli().

+

Referenced by mixPauli().

@@ -2516,14 +2516,14 @@

-

Definition at line 473 of file QuEST_validation.c.

- @@ -2553,14 +2553,14 @@

-

Definition at line 519 of file QuEST_validation.c.

-
519  {
-
520  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
-
521 }
+

Definition at line 523 of file QuEST_validation.c.

+
523  {
+
524  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
+
525 }
-

References E_INVALID_QUBIT_OUTCOME, and QuESTAssert().

+

References E_INVALID_QUBIT_OUTCOME, and QuESTAssert().

-

Referenced by calcProbOfOutcome(), collapseToOutcome(), and initStateOfSingleQubit().

+

Referenced by applyProjector(), calcProbOfOutcome(), collapseToOutcome(), and initStateOfSingleQubit().

@@ -2596,17 +2596,17 @@

-

Definition at line 595 of file QuEST_validation.c.

-
595  {
-
596  for (int i=0; i < numPauliCodes; i++) {
-
597  enum pauliOpType code = pauliCodes[i];
- -
599  }
-
600 }
+

Definition at line 599 of file QuEST_validation.c.

+
599  {
+
600  for (int i=0; i < numPauliCodes; i++) {
+
601  enum pauliOpType code = pauliCodes[i];
+ +
603  }
+
604 }
-

References E_INVALID_PAULI_CODE, isValidPauliCode(), and QuESTAssert().

+

References E_INVALID_PAULI_CODE, isValidPauliCode(), and QuESTAssert().

-

Referenced by applyPauliSum(), calcExpecPauliProd(), calcExpecPauliSum(), initPauliHamil(), multiControlledMultiRotatePauli(), multiRotatePauli(), and validatePauliHamil().

+

Referenced by applyPauliSum(), calcExpecPauliProd(), calcExpecPauliSum(), initPauliHamil(), multiControlledMultiRotatePauli(), multiRotatePauli(), and validatePauliHamil().

@@ -2636,15 +2636,15 @@

-

Definition at line 651 of file QuEST_validation.c.

- @@ -2686,63 +2686,63 @@

-

Definition at line 908 of file QuEST_validation.c.

-
908  {
-
909 
-
910  QuESTAssert(
-
911  funcCode == NORM ||
-
912  funcCode == INVERSE_NORM ||
-
913  funcCode == SCALED_NORM ||
-
914  funcCode == SCALED_INVERSE_NORM ||
-
915  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
-
916  funcCode == PRODUCT ||
-
917  funcCode == INVERSE_PRODUCT ||
-
918  funcCode == SCALED_PRODUCT ||
-
919  funcCode == SCALED_INVERSE_PRODUCT ||
-
920  funcCode == DISTANCE ||
-
921  funcCode == INVERSE_DISTANCE ||
-
922  funcCode == SCALED_DISTANCE ||
-
923  funcCode == SCALED_INVERSE_DISTANCE ||
- -
925  E_INVALID_PHASE_FUNC_NAME, caller);
-
926 
-
927  if (funcCode == NORM ||
-
928  funcCode == PRODUCT ||
-
929  funcCode == DISTANCE)
-
930  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
931 
-
932  if (funcCode == INVERSE_NORM ||
-
933  funcCode == INVERSE_PRODUCT ||
-
934  funcCode == INVERSE_DISTANCE)
-
935  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
936 
-
937  if (funcCode == SCALED_NORM ||
-
938  funcCode == SCALED_PRODUCT ||
-
939  funcCode == SCALED_DISTANCE)
+

Definition at line 913 of file QuEST_validation.c.

+
913  {
+
914 
+
915  QuESTAssert(
+
916  funcCode == NORM ||
+
917  funcCode == INVERSE_NORM ||
+
918  funcCode == SCALED_NORM ||
+
919  funcCode == SCALED_INVERSE_NORM ||
+
920  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
+
921  funcCode == PRODUCT ||
+
922  funcCode == INVERSE_PRODUCT ||
+
923  funcCode == SCALED_PRODUCT ||
+
924  funcCode == SCALED_INVERSE_PRODUCT ||
+
925  funcCode == DISTANCE ||
+
926  funcCode == INVERSE_DISTANCE ||
+
927  funcCode == SCALED_DISTANCE ||
+
928  funcCode == SCALED_INVERSE_DISTANCE ||
+ +
930  E_INVALID_PHASE_FUNC_NAME, caller);
+
931 
+
932  if (funcCode == NORM ||
+
933  funcCode == PRODUCT ||
+
934  funcCode == DISTANCE)
+
935  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
936 
+
937  if (funcCode == INVERSE_NORM ||
+
938  funcCode == INVERSE_PRODUCT ||
+
939  funcCode == INVERSE_DISTANCE)
940  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
941 
-
942  if (funcCode == SCALED_INVERSE_NORM ||
-
943  funcCode == SCALED_INVERSE_PRODUCT ||
-
944  funcCode == SCALED_INVERSE_DISTANCE)
-
945  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
946 
-
947  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
-
948  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
949 
-
950  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
-
951  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
-
952 
-
953  if (funcCode == DISTANCE ||
-
954  funcCode == INVERSE_DISTANCE ||
-
955  funcCode == SCALED_DISTANCE ||
-
956  funcCode == SCALED_INVERSE_DISTANCE ||
- -
958  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
-
959 }
-
-

References DISTANCE, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, E_INVALID_PHASE_FUNC_NAME, INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, NORM, PRODUCT, QuESTAssert(), SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, and SCALED_PRODUCT.

- -

Referenced by applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+
942  if (funcCode == SCALED_NORM ||
+
943  funcCode == SCALED_PRODUCT ||
+
944  funcCode == SCALED_DISTANCE)
+
945  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
946 
+
947  if (funcCode == SCALED_INVERSE_NORM ||
+
948  funcCode == SCALED_INVERSE_PRODUCT ||
+
949  funcCode == SCALED_INVERSE_DISTANCE)
+
950  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
951 
+
952  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
+
953  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
954 
+
955  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
+
956  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
+
957 
+
958  if (funcCode == DISTANCE ||
+
959  funcCode == INVERSE_DISTANCE ||
+
960  funcCode == SCALED_DISTANCE ||
+
961  funcCode == SCALED_INVERSE_DISTANCE ||
+ +
963  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
+
964 }
+
+

References DISTANCE, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, E_INVALID_PHASE_FUNC_NAME, INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, NORM, PRODUCT, QuESTAssert(), SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, and SCALED_PRODUCT.

+ +

Referenced by applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -2790,34 +2790,34 @@

-

Definition at line 857 of file QuEST_validation.c.

-
857  {
-
858  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
859  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
-
860 
-
861  long long int maxInd;
-
862  long long int minInd;
-
863 
-
864  if (encoding == UNSIGNED) {
-
865  minInd = 0;
-
866  maxInd = (1LL << numQubits) - 1;
-
867  for (int v=0; v<numOverrides; v++)
-
868  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
-
869  }
-
870 
-
871  if (encoding == TWOS_COMPLEMENT) {
-
872  int numValQubits = numQubits - 1; // removing sign bit
-
873  minInd = - (1LL << numValQubits);
-
874  maxInd = (1LL << numValQubits) - 1;
-
875  for (int v=0; v<numOverrides; v++)
-
876  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
-
877  }
-
878 
-
879 }
+

Definition at line 862 of file QuEST_validation.c.

+
862  {
+
863  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
864  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
+
865 
+
866  long long int maxInd;
+
867  long long int minInd;
+
868 
+
869  if (encoding == UNSIGNED) {
+
870  minInd = 0;
+
871  maxInd = (1LL << numQubits) - 1;
+
872  for (int v=0; v<numOverrides; v++)
+
873  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
+
874  }
+
875 
+
876  if (encoding == TWOS_COMPLEMENT) {
+
877  int numValQubits = numQubits - 1; // removing sign bit
+
878  minInd = - (1LL << numValQubits);
+
879  maxInd = (1LL << numValQubits) - 1;
+
880  for (int v=0; v<numOverrides; v++)
+
881  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
+
882  }
+
883 
+
884 }
-

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

+

References E_INVALID_NUM_PHASE_FUNC_OVERRIDES, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, QuESTAssert(), TWOS_COMPLEMENT, and UNSIGNED.

-

Referenced by applyPhaseFuncOverrides().

+

Referenced by applyPhaseFuncOverrides().

@@ -2883,72 +2883,73 @@

-

Definition at line 769 of file QuEST_validation.c.

-
769  {
-
770  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
-
771 
-
772  int hasFractionExpo = 0;
-
773  int hasNegativeExpo = 0;
-
774  for (int t=0; t<numTerms; t++) {
-
775  // this is only true if exponent is precisely an integer, else pow() will NaN
-
776  if (floor(exponents[t]) != exponents[t])
-
777  hasFractionExpo = 1;
-
778  if (exponents[t] < 0)
-
779  hasNegativeExpo = 1;
-
780  }
-
781 
-
782  // ensure negative exponents are supplied along with a zero-index override
-
783  if (hasNegativeExpo) {
-
784  int hasZeroOverride = 0;
-
785  for (int v=0; v<numOverrides; v++) {
-
786  if (overrideInds[v] == 0LL) {
-
787  hasZeroOverride = 1;
-
788  break;
-
789  }
-
790  }
-
791  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
-
792  }
-
793 
-
794  // ensure fractional powers not used with negative numbers, unless overriden
-
795  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
-
796  long long int numNegInds = (1LL << (numQubits-1));
-
797 
-
798  // immediately disqualify if insufficient overrides are given to cover every negative number
-
799  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
-
800 
-
801  int allNegsOverriden;
-
802 
-
803  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
-
804  if (numQubits < 16) {
-
805 
-
806  long long int negIsOverriden[numNegInds]; // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
-
807  for (int i=0; i<numNegInds; i++)
-
808  negIsOverriden[i] = 0;
+

Definition at line 773 of file QuEST_validation.c.

+
773  {
+
774  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
+
775 
+
776  int hasFractionExpo = 0;
+
777  int hasNegativeExpo = 0;
+
778  for (int t=0; t<numTerms; t++) {
+
779  // this is only true if exponent is precisely an integer, else pow() will NaN
+
780  if (floor(exponents[t]) != exponents[t])
+
781  hasFractionExpo = 1;
+
782  if (exponents[t] < 0)
+
783  hasNegativeExpo = 1;
+
784  }
+
785 
+
786  // ensure negative exponents are supplied along with a zero-index override
+
787  if (hasNegativeExpo) {
+
788  int hasZeroOverride = 0;
+
789  for (int v=0; v<numOverrides; v++) {
+
790  if (overrideInds[v] == 0LL) {
+
791  hasZeroOverride = 1;
+
792  break;
+
793  }
+
794  }
+
795  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
+
796  }
+
797 
+
798  // ensure fractional powers not used with negative numbers, unless overriden
+
799  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
+
800  long long int numNegInds = (1LL << (numQubits-1));
+
801 
+
802  // immediately disqualify if insufficient overrides are given to cover every negative number
+
803  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
+
804 
+
805  int allNegsOverriden;
+
806 
+
807  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
+
808  if (numQubits < 16) {
809 
-
810  for (int v=0; v<numOverrides; v++)
-
811  if (overrideInds[v] < 0)
-
812  negIsOverriden[ -1 - overrideInds[v] ] = 1;
-
813 
-
814  allNegsOverriden = 1;
-
815  for (int i=0; i<numNegInds; i++) {
-
816  if (!negIsOverriden[i]) {
-
817  allNegsOverriden = 0;
-
818  break;
-
819  }
-
820  }
-
821  }
-
822  // otherwise, we must trust the user, else impose significant slowdowns on good users
-
823  else {
-
824  allNegsOverriden = 1;
-
825  }
-
826 
-
827  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
-
828  }
-
829 }
-
-

References E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, E_INVALID_NUM_PHASE_FUNC_TERMS, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, QuESTAssert(), and TWOS_COMPLEMENT.

- -

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

+
810  // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
+
811  long long int negIsOverriden[32768]; // [numNegInds];
+
812  for (int i=0; i<numNegInds; i++)
+
813  negIsOverriden[i] = 0;
+
814 
+
815  for (int v=0; v<numOverrides; v++)
+
816  if (overrideInds[v] < 0)
+
817  negIsOverriden[ -1 - overrideInds[v] ] = 1;
+
818 
+
819  allNegsOverriden = 1;
+
820  for (int i=0; i<numNegInds; i++) {
+
821  if (!negIsOverriden[i]) {
+
822  allNegsOverriden = 0;
+
823  break;
+
824  }
+
825  }
+
826  }
+
827  // otherwise, we must trust the user, else impose significant slowdowns on good users
+
828  else {
+
829  allNegsOverriden = 1;
+
830  }
+
831 
+
832  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
+
833  }
+
834 }
+
+

References E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, E_INVALID_NUM_PHASE_FUNC_TERMS, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, QuESTAssert(), and TWOS_COMPLEMENT.

+ +

Referenced by applyPhaseFunc(), and applyPhaseFuncOverrides().

@@ -2978,14 +2979,14 @@

-

Definition at line 547 of file QuEST_validation.c.

- @@ -3033,26 +3034,26 @@

-

Definition at line 753 of file QuEST_validation.c.

-
753  {
- -
755 
-
756  int i=0;
-
757  for (int r=0; r<numRegs; r++) {
-
758  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+

Definition at line 757 of file QuEST_validation.c.

+
757  {
+
759 
-
760  for (int q=0; q < numQubitsPerReg[r]; q++) {
-
761  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
-
762  i++;
-
763  }
-
764  }
-
765 
-
766  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
-
767 }
+
760  int i=0;
+
761  for (int r=0; r<numRegs; r++) {
+
762  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
+
763 
+
764  for (int q=0; q < numQubitsPerReg[r]; q++) {
+
765  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
+
766  i++;
+
767  }
+
768  }
+
769 
+
770  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
+
771 }
-

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_NUM_SUBREGISTERS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, Qureg::numQubitsRepresented, and QuESTAssert().

+

References areUniqueQubits(), E_INVALID_NUM_QUBITS, E_INVALID_NUM_SUBREGISTERS, E_INVALID_QUBIT_INDEX, E_QUBITS_NOT_UNIQUE, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, Qureg::numQubitsRepresented, and QuESTAssert().

-

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

+

Referenced by applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), and applyParamNamedPhaseFuncOverrides().

@@ -3082,14 +3083,14 @@

-

Definition at line 535 of file QuEST_validation.c.

-
535  {
- -
537 }
+

Definition at line 539 of file QuEST_validation.c.

+
539  {
+ +
541 }
-

References E_SECOND_ARG_MUST_BE_STATEVEC, Qureg::isDensityMatrix, and QuESTAssert().

+

References E_SECOND_ARG_MUST_BE_STATEVEC, Qureg::isDensityMatrix, and QuESTAssert().

-

Referenced by calcFidelity(), and initPureState().

+

Referenced by calcFidelity(), and initPureState().

@@ -3125,13 +3126,13 @@

-

Definition at line 373 of file QuEST_validation.c.

-
373  {
-
374  long long int stateMax = 1LL << qureg.numQubitsRepresented;
-
375  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
-
376 }
+

Definition at line 377 of file QuEST_validation.c.

+
377  {
+
378  long long int stateMax = 1LL << qureg.numQubitsRepresented;
+
379  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
+
380 }
-

References E_INVALID_STATE_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

+

References E_INVALID_STATE_INDEX, Qureg::numQubitsRepresented, and QuESTAssert().

Referenced by initClassicalState().

@@ -3163,14 +3164,14 @@

-

Definition at line 511 of file QuEST_validation.c.

-

@@ -3206,14 +3207,14 @@

-

Definition at line 396 of file QuEST_validation.c.

- @@ -3249,16 +3250,16 @@

-

Definition at line 699 of file QuEST_validation.c.

-
699  {
-
700  int isEven = (order % 2) == 0;
-
701  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
-
702  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
-
703 }
+

Definition at line 703 of file QuEST_validation.c.

+
703  {
+
704  int isEven = (order % 2) == 0;
+
705  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
+
706  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
+
707 }
-

References E_INVALID_TROTTER_ORDER, E_INVALID_TROTTER_REPS, and QuESTAssert().

+

References E_INVALID_TROTTER_ORDER, E_INVALID_TROTTER_REPS, and QuESTAssert().

-

Referenced by applyTrotterCircuit().

+

Referenced by applyTrotterCircuit().

@@ -3288,15 +3289,15 @@

-

Definition at line 564 of file QuEST_validation.c.

-
564  {
-
565  validateProb(prob, caller);
-
566  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
-
567 }
+

Definition at line 568 of file QuEST_validation.c.

+
568  {
+
569  validateProb(prob, caller);
+
570  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
+
571 }
-

References E_INVALID_TWO_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_TWO_QUBIT_DEPHASE_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixTwoQubitDephasing().

+

Referenced by mixTwoQubitDephasing().

@@ -3326,15 +3327,15 @@

-

Definition at line 579 of file QuEST_validation.c.

-
579  {
-
580  validateProb(prob, caller);
-
581  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
-
582 }
+

Definition at line 583 of file QuEST_validation.c.

+
583  {
+
584  validateProb(prob, caller);
+
585  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
+
586 }
-

References E_INVALID_TWO_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

+

References E_INVALID_TWO_QUBIT_DEPOL_PROB, QuESTAssert(), and validateProb().

-

Referenced by mixTwoQubitDepolarising().

+

Referenced by mixTwoQubitDepolarising().

@@ -3376,22 +3377,22 @@

-

Definition at line 618 of file QuEST_validation.c.

-
618  {
-
619  int opNumQubits = 2;
-
620  int superOpNumQubits = 2*opNumQubits;
-
621  int maxNumOps = superOpNumQubits*superOpNumQubits;
-
622  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
-
623 
-
624  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
-
625 
-
626  int isPos = isCompletelyPositiveMap4(ops, numOps);
-
627  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
-
628 }
+

Definition at line 622 of file QuEST_validation.c.

+
622  {
+
623  int opNumQubits = 2;
+
624  int superOpNumQubits = 2*opNumQubits;
+
625  int maxNumOps = superOpNumQubits*superOpNumQubits;
+
626  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
+
627 
+
628  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
+
629 
+
630  int isPos = isCompletelyPositiveMap4(ops, numOps);
+
631  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
+
632 }
-

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, isCompletelyPositiveMap4(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

+

References E_INVALID_KRAUS_OPS, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, isCompletelyPositiveMap4(), QuESTAssert(), and validateMultiQubitMatrixFitsInNode().

-

Referenced by mixTwoQubitKrausMap().

+

Referenced by mixTwoQubitKrausMap().

@@ -3427,15 +3428,15 @@

-

Definition at line 477 of file QuEST_validation.c.

- @@ -3477,16 +3478,16 @@

-

Definition at line 410 of file QuEST_validation.c.

-
410  {
-
411  validateTarget(qureg, qubit1, caller);
-
412  validateTarget(qureg, qubit2, caller);
-
413  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
-
414 }
+

Definition at line 414 of file QuEST_validation.c.

+
414  {
+
415  validateTarget(qureg, qubit1, caller);
+
416  validateTarget(qureg, qubit2, caller);
+
417  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
+
418 }
-

References E_TARGETS_NOT_UNIQUE, QuESTAssert(), and validateTarget().

+

References E_TARGETS_NOT_UNIQUE, QuESTAssert(), and validateTarget().

-

Referenced by mixTwoQubitDephasing(), mixTwoQubitDepolarising(), sqrtSwapGate(), and swapGate().

+

Referenced by mixTwoQubitDephasing(), mixTwoQubitDepolarising(), sqrtSwapGate(), and swapGate().

@@ -3522,14 +3523,14 @@

-

Definition at line 503 of file QuEST_validation.c.

-
503  {
- -
505 }
+

Definition at line 507 of file QuEST_validation.c.

+
507  {
+ +
509 }
-

References E_NON_UNITARY_COMPLEX_PAIR, isComplexPairUnitary(), and QuESTAssert().

+

References E_NON_UNITARY_COMPLEX_PAIR, isComplexPairUnitary(), and QuESTAssert().

-

Referenced by compactUnitary(), and controlledCompactUnitary().

+

Referenced by compactUnitary(), and controlledCompactUnitary().

@@ -3559,14 +3560,14 @@

-

Definition at line 507 of file QuEST_validation.c.

-
507  {
-
508  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
-
509 }
+

Definition at line 511 of file QuEST_validation.c.

+
511  {
+
512  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
+
513 }
-

References E_ZERO_VECTOR, getVectorMagnitude(), and QuESTAssert().

+

References E_ZERO_VECTOR, getVectorMagnitude(), and QuESTAssert().

-

Referenced by controlledRotateAroundAxis(), and rotateAroundAxis().

+

Referenced by controlledRotateAroundAxis(), and rotateAroundAxis().

@@ -3575,34 +3576,34 @@

pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
@ E_NUM_AMPS_EXCEED_TYPE
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
@ E_MISMATCHING_PAULI_HAMIL_DIAGONAL_OP_SIZE
@ E_INVALID_QUBIT_OUTCOME
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
-
int isMatrix2Unitary(ComplexMatrix2 u)
+
int isMatrix2Unitary(ComplexMatrix2 u)
@ E_PAULI_HAMIL_NOT_DIAGONAL
@ PAULI_Z
Definition: QuEST.h:96
@ DISTANCE
Definition: QuEST.h:234
@ E_INVALID_NUM_PHASE_FUNC_TERMS
@ E_INVALID_PAULI_CODE
@ E_NON_UNITARY_MATRIX
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
+
void validateHamilParams(int numQubits, int numTerms, const char *caller)
@ PAULI_I
Definition: QuEST.h:96
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
+
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
@ E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
@ E_INVALID_ELEM_INDEX
-
int isMatrix4Unitary(ComplexMatrix4 u)
+
int isMatrix4Unitary(ComplexMatrix4 u)
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
@ E_MISMATCHING_QUREG_TYPES
-
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
-
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
+
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
+
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
@ E_INVALID_QUBIT_INDEX
@ E_INVALID_PHASE_FUNC_NAME
-
void validateProb(qreal prob, const char *caller)
+
void validateProb(qreal prob, const char *caller)
@ E_INVALID_BIT_ENCODING
@ NORM
Definition: QuEST.h:232
@ E_NON_UNITARY_COMPLEX_PAIR
@@ -3618,24 +3619,24 @@

@ E_INVALID_NUM_SUM_TERMS
@ E_DEFINED_ONLY_FOR_STATEVECS
#define qreal
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
+
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
+
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
@ E_NEGATIVE_EXPONENT_MULTI_VAR
-
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
-
void validateControl(Qureg qureg, int controlQubit, const char *caller)
+
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
+
void validateControl(Qureg qureg, int controlQubit, const char *caller)
@ E_INVALID_PROB
-
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
-
int isMatrixNUnitary(ComplexMatrixN u)
+
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
+
int isMatrixNUnitary(ComplexMatrixN u)
@ E_QUBITS_NOT_UNIQUE
@ E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX
@ E_CONTROL_TARGET_COLLISION
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
+
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
@ E_DEFINED_ONLY_FOR_DENSMATRS
@ E_INVALID_KRAUS_OPS
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
@ E_INVALID_STATE_INDEX
-
int areUniqueQubits(int *qubits, int numQubits)
+
int areUniqueQubits(int *qubits, int numQubits)
@ E_TARGET_IN_CONTROLS
@ E_INVALID_NUM_QUBITS
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
@@ -3646,8 +3647,8 @@

enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
@ SCALED_PRODUCT
Definition: QuEST.h:233
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
int isValidPauliCode(enum pauliOpType code)
+
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
+
int isValidPauliCode(enum pauliOpType code)
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
@ E_INVALID_TARGET_QUBIT
@ E_COMPLEX_MATRIX_NOT_INIT
@@ -3665,7 +3666,7 @@

@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
static const char * errorMessages[]
-
void QuESTAssert(int isValid, ErrorCode code, const char *func)
+
void QuESTAssert(int isValid, ErrorCode code, const char *func)
@ E_INVALID_NUM_AMPS
@ E_COLLAPSE_STATE_ZERO_PROB
@ E_TARGETS_NOT_UNIQUE
@@ -3676,11 +3677,11 @@

@ PRODUCT
Definition: QuEST.h:233
char errMsgBuffer[1024]
@ E_INVALID_NUM_CREATE_QUBITS
-
void validateDiagOpInit(DiagonalOp op, const char *caller)
+
void validateDiagOpInit(DiagonalOp op, const char *caller)
@ E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
int numQubits
Definition: QuEST.h:188
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
+
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
@@ -3693,17 +3694,17 @@

@ SCALED_DISTANCE
Definition: QuEST.h:234
@ E_FRACTIONAL_EXPONENT_MULTI_VAR
@ E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT
-
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1399
-
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
+
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1414
+
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
+
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
@ E_INVALID_NUM_ELEMS
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
@ E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
-
int isComplexPairUnitary(Complex alpha, Complex beta)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
+
int isComplexPairUnitary(Complex alpha, Complex beta)
+
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
@ E_DIAGONAL_OP_NOT_INITIALISED
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
@ E_ZERO_VECTOR
diff --git a/docs/QuEST__validation_8h_source.html b/docs/QuEST__validation_8h_source.html index c5d35b49c..bf8448a92 100644 --- a/docs/QuEST__validation_8h_source.html +++ b/docs/QuEST__validation_8h_source.html @@ -27,7 +27,7 @@ @@ -208,85 +208,85 @@
156 
157 # endif // QUEST_VALIDATION_H
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
-
void validateNumPauliSumTerms(int numTerms, const char *caller)
+
void validateOneQubitDephaseProb(qreal prob, const char *caller)
+
void validateNumPauliSumTerms(int numTerms, const char *caller)
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
-
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
-
void validateHamilParams(int numQubits, int numTerms, const char *caller)
-
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
-
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
-
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
-
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
-
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
-
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numReg, const char *caller)
-
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
-
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
-
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
-
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
-
void validateNumQubitsInMatrix(int numQubits, const char *caller)
-
void validateNumRanks(int numRanks, const char *caller)
-
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
-
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateStateVecQureg(Qureg qureg, const char *caller)
+
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
+
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
+
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
+
void validateHamilParams(int numQubits, int numTerms, const char *caller)
+
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
+
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
+
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
+
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
+
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
+
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
+
void validateOneQubitDepolProb(qreal prob, const char *caller)
+
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numReg, const char *caller)
+
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
+
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
+
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
+
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
+
void validateNumQubitsInMatrix(int numQubits, const char *caller)
+
void validateNumRanks(int numRanks, const char *caller)
+
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
+
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void validateStateVecQureg(Qureg qureg, const char *caller)
-
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
-
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
+
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
+
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
-
void validateDiagPauliHamilFromFile(PauliHamil h, int numRanks, const char *caller)
+
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
+
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
+
void validateDiagPauliHamilFromFile(PauliHamil h, int numRanks, const char *caller)
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
-
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
-
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
+
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
#define qreal
-
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
-
void validateMeasurementProb(qreal prob, const char *caller)
-
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
-
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
-
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
-
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
+
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
+
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
+
void validateMeasurementProb(qreal prob, const char *caller)
+
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
+
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
+
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
+
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
-
void validateControlState(int *controlState, int numControlQubits, const char *caller)
-
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
-
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void validateOutcome(int outcome, const char *caller)
-
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
+
void validateControlState(int *controlState, int numControlQubits, const char *caller)
+
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
+
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void validateOutcome(int outcome, const char *caller)
+
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
-
void validateMultiTargets(Qureg qurge, int *targetQubits, int numTargetQubits, const char *caller)
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
-
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
+
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
+
void validateTwoQubitDepolProb(qreal prob, const char *caller)
+
void validateMultiTargets(Qureg qurge, int *targetQubits, int numTargetQubits, const char *caller)
+
void validatePauliHamil(PauliHamil hamil, const char *caller)
+
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
Represents a system of qubits.
Definition: QuEST.h:322
-
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
-
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
-
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
-
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
-
void validateProb(qreal prob, const char *caller)
-
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
-
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
-
void validateFileOpened(int opened, char *fn, const char *caller)
-
void validateTrotterParams(int order, int reps, const char *caller)
+
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
+
void validateDensityMatrQureg(Qureg qureg, const char *caller)
+
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
+
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
+
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
+
void validateProb(qreal prob, const char *caller)
+
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
+
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
+
void validateFileOpened(int opened, char *fn, const char *caller)
+
void validateTrotterParams(int order, int reps, const char *caller)
Represents one complex number.
Definition: QuEST.h:103
-
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
-
void validateDiagOpInit(DiagonalOp, const char *caller)
-
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
-
void validateVector(Vector vector, const char *caller)
+
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
+
void validateOneQubitDampingProb(qreal prob, const char *caller)
+
void validateDiagOpInit(DiagonalOp, const char *caller)
+
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
+
void validateVector(Vector vector, const char *caller)
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
-
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
+
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
-
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
+
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
diff --git a/docs/README_8md.html b/docs/README_8md.html index df9f89c73..f3bc7d918 100644 --- a/docs/README_8md.html +++ b/docs/README_8md.html @@ -27,7 +27,7 @@ diff --git a/docs/classSequenceGenerator.html b/docs/classSequenceGenerator.html index eec0274f2..e2b6bb980 100644 --- a/docs/classSequenceGenerator.html +++ b/docs/classSequenceGenerator.html @@ -27,7 +27,7 @@ diff --git a/docs/classSubListGenerator.html b/docs/classSubListGenerator.html index 7427eae32..cfc7b92d6 100644 --- a/docs/classSubListGenerator.html +++ b/docs/classSubListGenerator.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html b/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html index a86254922..528e97e00 100644 --- a/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html +++ b/docs/dir_126ffd7f5d49d0bf631a939d5b00372b.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html b/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html index 472168319..993560832 100644 --- a/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html +++ b/docs/dir_288db1ec25fc0ec29a6dc915511dd336.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html b/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html index 4629cab62..5b2a009f0 100644 --- a/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html +++ b/docs/dir_9ac8631f294bc067d7e4c007a43fb043.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_aaf4e0c86438000dc030ca371e863336.html b/docs/dir_aaf4e0c86438000dc030ca371e863336.html index 90e375fee..1a374b0fb 100644 --- a/docs/dir_aaf4e0c86438000dc030ca371e863336.html +++ b/docs/dir_aaf4e0c86438000dc030ca371e863336.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_ab07507df26ab10c8d894f4336a7987b.html b/docs/dir_ab07507df26ab10c8d894f4336a7987b.html index c27b0e173..c0555377c 100644 --- a/docs/dir_ab07507df26ab10c8d894f4336a7987b.html +++ b/docs/dir_ab07507df26ab10c8d894f4336a7987b.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html b/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html index f2cb9cb66..b5752238f 100644 --- a/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html +++ b/docs/dir_e145b6391efe0b6e575fd5bb5f76dbf8.html @@ -27,7 +27,7 @@ diff --git a/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html b/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html index 328475311..003f7a48c 100644 --- a/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html +++ b/docs/dir_ea73998990134951f0a2a9d1cfc118c0.html @@ -27,7 +27,7 @@ diff --git a/docs/files.html b/docs/files.html index 0410da4ce..64673f88f 100644 --- a/docs/files.html +++ b/docs/files.html @@ -27,7 +27,7 @@ diff --git a/docs/form_305.png b/docs/form_305.png index d0d1119bb..361d2b835 100644 Binary files a/docs/form_305.png and b/docs/form_305.png differ diff --git a/docs/formula.repository b/docs/formula.repository index b0596abde..bd6161266 100644 --- a/docs/formula.repository +++ b/docs/formula.repository @@ -303,6 +303,6 @@ \_form#302:$j\text{th}$ \_form#303:$n =$ \_form#304:$N =$ -\_form#305:\[ (\text{QFT}\otimes 1) \, \left( \sum\limits_{j=0}^{2^N-1} \alpha_j \, |x_j,r_j\rangle \right) = \frac{1}{\sqrt{2^n}} \sum\limits_{j=0}^{2^N-1} \alpha_j \left( \sum\limits_{y=0}^{2^n-1} e^{2 \pi \, i \, x_j \, y / 2^N} \; |y,r_j \rangle \right) \] +\_form#305:\[ (\text{QFT}\otimes 1) \, \left( \sum\limits_{j=0}^{2^N-1} \alpha_j \, |x_j,r_j\rangle \right) = \frac{1}{\sqrt{2^n}} \sum\limits_{j=0}^{2^N-1} \alpha_j \left( \sum\limits_{y=0}^{2^n-1} e^{2 \pi \, i \, x_j \, y / 2^n} \; |y,r_j \rangle \right) \] \_form#306:\[ \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger \] \_form#307:\[ \text{state} \to \text{op} \, \text{state} \] diff --git a/docs/globals.html b/docs/globals.html index ba4ad2bfb..f97bd619f 100644 --- a/docs/globals.html +++ b/docs/globals.html @@ -27,7 +27,7 @@ diff --git a/docs/globals_a.html b/docs/globals_a.html index 2c0fe524a..57c14b064 100644 --- a/docs/globals_a.html +++ b/docs/globals_a.html @@ -27,7 +27,7 @@ @@ -174,30 +174,40 @@

- a -

+ + + @@ -92,12 +95,12 @@ - - - - - - + + + + + + @@ -151,13 +154,13 @@

Definition at line 39 of file QuEST_cpu.c.

- @@ -197,13 +200,13 @@

Definition at line 36 of file QuEST_cpu.c.

-
36  {
-
37 }
+

Definition at line 42 of file QuEST_cpu.c.

+
42  {
+
43 }

References DEBUG, Qureg::deviceStateVec, Qureg::numAmpsPerChunk, and Qureg::stateVec.

-

Referenced by statevec_initStateFromSingleFile(), TEST_CASE(), and toQureg().

+

Referenced by statevec_initStateFromSingleFile(), TEST_CASE(), and toQureg().

@@ -248,18 +251,88 @@

Definition at line 194 of file QuEST_cpu_distributed.c.

-
194  {
-
195  int ompStatus=0;
-
196  int numThreads=1;
-
197 # ifdef _OPENMP
-
198  ompStatus=1;
-
199  numThreads=omp_get_max_threads();
-
200 # endif
-
201  sprintf(str, "CUDA=0 OpenMP=%d MPI=1 threads=%d ranks=%d", ompStatus, numThreads, env.numRanks);
-
202 }
+

Definition at line 198 of file QuEST_cpu_distributed.c.

+
198  {
+
199  int ompStatus=0;
+
200  int numThreads=1;
+
201 # ifdef _OPENMP
+
202  ompStatus=1;
+
203  numThreads=omp_get_max_threads();
+
204 # endif
+
205  sprintf(str, "CUDA=0 OpenMP=%d MPI=1 threads=%d ranks=%d", ompStatus, numThreads, env.numRanks);
+
206 }
-

References QuESTEnv::numRanks.

+

References QuESTEnv::numRanks.

+ +
+ + +

◆ getQuESTSeeds()

+ +
+
+

void exitWithError void default_invalidQuESTInputError ( const char * msg, errMsg,
const char * func errFunc 
void getEnvironmentString (QuESTEnv env, char str[200])
 Sets str to a string containing information about the runtime environment, including whether simulation is using CUDA (for GPU), OpenMP (for multithreading) and/or MPI (for distribution). More...
 
void getQuESTSeeds (QuESTEnv env, unsigned long int **seeds, int *numSeeds)
 Obtain the seeds presently used in random number generation. More...
 
void initDebugState (Qureg qureg)
 Initialises qureg to be in the un-normalised, non-physical state with with $n$-th complex amplitude given by $2n/10 + i(2n+1)/10$. More...
 
void reportStateToScreen (Qureg qureg, QuESTEnv env, int reportRank)
 Print the current state vector of probability amplitudes for a set of qubits to standard out. More...
 
void seedQuEST (unsigned long int *seedArray, int numSeeds)
 Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed. More...
 
void seedQuESTDefault (void)
 Seed the Mersenne Twister used for random number generation in the QuEST environment with an example default seed. More...
 
void seedQuEST (QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
 Seeds the random number generator with a custom array of key(s), overriding the default keys. More...
 
void seedQuESTDefault (QuESTEnv *env)
 Seeds the random number generator with the (master node) current time and process ID. More...
 
void syncQuESTEnv (QuESTEnv env)
 Guarantees that all code up to the given point has been executed on all nodes (if running in distributed mode) More...
 
+ + + + + + + + + + + + + + + + + + + + + + + +
void getQuESTSeeds (QuESTEnv env,
unsigned long int ** seeds,
int * numSeeds 
)
+
+ +

Obtain the seeds presently used in random number generation.

+

This function sets argument seeds to the address of the array of keys which have seeded QuEST's Mersenne Twister random number generator. numSeeds is set to the length of seeds. These are the seeds which inform the outcomes of random functions like measure(), and are set using seedQuEST() and seedQuESTDefault().

+
+

The output seeds array must not be freed, and should not be modified.

+
+

Obtaining QuEST's seeds is useful for seeding your own random number generators, so that a simulation (with random QuEST measurements, and your own random decisions) can be precisely repeated later, just by calling seedQuEST().

+

Note this function merely sets the arguments to the attributes for env. I.e.

unsigned long int* seeds;
+
int numSeeds;
+
getQuESTSeeds(env, &seeds, &numSeeds);
+
+
func(seeds, numSeeds);
+

is equivalent to

func(env.seeds, env.numSeeds);
+

However, one should not rely upon their local pointer from getQuESTSeeds() to be automatically updated after a subsequent call to seedQuEST() or seedQuESTDefault(). Instead, getQuESTSeeds() should be recalled.

+
See also
+
+
Parameters
+ + + + +
[in]envthe QuESTEnv runtime environment
[in]seedsa pointer to an unitialised array to be modified
[in]numSeedsa pointer to an integer to be modified
+
+
+
Author
Tyson Jones
+ +

Definition at line 1622 of file QuEST.c.

+
1622  {
+
1623  *seeds = env.seeds;
+
1624  *numSeeds = env.numSeeds;
+
1625 }
+
+

References QuESTEnv::numSeeds, and QuESTEnv::seeds.

@@ -291,12 +364,12 @@

Definition at line 1563 of file QuEST.c.

-
1563  {
-
1564  statevec_initDebugState(qureg);
-
1565 }
+

Definition at line 1578 of file QuEST.c.

+
1578  {
+
1579  statevec_initDebugState(qureg);
+
1580 }
-

References statevec_initDebugState().

+

References statevec_initDebugState().

Referenced by TEST_CASE().

@@ -366,14 +439,14 @@

Definition at line 208 of file QuEST_validation.c.

-

@@ -416,20 +489,20 @@

Author
Tyson Jones
-

Definition at line 1583 of file QuEST.c.

-
1583  {
-
1584  validatePauliHamil(hamil, __func__);
-
1585 
-
1586  for (int t=0; t<hamil.numSumTerms; t++) {
-
1587  printf(REAL_QASM_FORMAT, hamil.termCoeffs[t]);
-
1588  printf("\t");
-
1589  for (int q=0; q<hamil.numQubits; q++)
-
1590  printf("%d ", (int) hamil.pauliCodes[q+t*hamil.numQubits]);
-
1591  printf("\n");
-
1592  }
-
1593 }
+

Definition at line 1598 of file QuEST.c.

+
1598  {
+
1599  validatePauliHamil(hamil, __func__);
+
1600 
+
1601  for (int t=0; t<hamil.numSumTerms; t++) {
+
1602  printf(REAL_QASM_FORMAT, hamil.termCoeffs[t]);
+
1603  printf("\t");
+
1604  for (int q=0; q<hamil.numQubits; q++)
+
1605  printf("%d ", (int) hamil.pauliCodes[q+t*hamil.numQubits]);
+
1606  printf("\n");
+
1607  }
+
1608 }
-

References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and validatePauliHamil().

+

References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and validatePauliHamil().

@@ -458,23 +531,23 @@

Author
Ania Brown
-

Definition at line 179 of file QuEST_cpu_distributed.c.

-
179  {
-
180  if (env.rank==0){
-
181  printf("EXECUTION ENVIRONMENT:\n");
-
182  printf("Running distributed (MPI) version\n");
-
183  printf("Number of ranks is %d\n", env.numRanks);
-
184 # ifdef _OPENMP
-
185  printf("OpenMP enabled\n");
-
186  printf("Number of threads available is %d\n", omp_get_max_threads());
-
187 # else
-
188  printf("OpenMP disabled\n");
-
189 # endif
-
190  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal) );
-
191  }
-
192 }
+

Definition at line 183 of file QuEST_cpu_distributed.c.

+
183  {
+
184  if (env.rank==0){
+
185  printf("EXECUTION ENVIRONMENT:\n");
+
186  printf("Running distributed (MPI) version\n");
+
187  printf("Number of ranks is %d\n", env.numRanks);
+
188 # ifdef _OPENMP
+
189  printf("OpenMP enabled\n");
+
190  printf("Number of threads available is %d\n", omp_get_max_threads());
+
191 # else
+
192  printf("OpenMP disabled\n");
+
193 # endif
+
194  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal) );
+
195  }
+
196 }
-

References QuESTEnv::numRanks, qreal, and QuESTEnv::rank.

+

References QuESTEnv::numRanks, qreal, and QuESTEnv::rank.

@@ -503,17 +576,17 @@

Author
Ania Brown
-

Definition at line 247 of file QuEST_common.c.

-
247  {
-
248  long long int numAmps = 1LL << qureg.numQubitsInStateVec;
-
249  long long int numAmpsPerRank = numAmps/qureg.numChunks;
-
250  if (qureg.chunkId==0){
-
251  printf("QUBITS:\n");
-
252  printf("Number of qubits is %d.\n", qureg.numQubitsInStateVec);
-
253  printf("Number of amps is %lld.\n", numAmps);
-
254  printf("Number of amps per rank is %lld.\n", numAmpsPerRank);
-
255  }
-
256 }
+

Definition at line 237 of file QuEST_common.c.

+
237  {
+
238  long long int numAmps = 1LL << qureg.numQubitsInStateVec;
+
239  long long int numAmpsPerRank = numAmps/qureg.numChunks;
+
240  if (qureg.chunkId==0){
+
241  printf("QUBITS:\n");
+
242  printf("Number of qubits is %d.\n", qureg.numQubitsInStateVec);
+
243  printf("Number of amps is %lld.\n", numAmps);
+
244  printf("Number of amps per rank is %lld.\n", numAmpsPerRank);
+
245  }
+
246 }

References Qureg::chunkId, Qureg::numChunks, and Qureg::numQubitsInStateVec.

@@ -552,24 +625,24 @@

Author
Ania Brown
-

Definition at line 229 of file QuEST_common.c.

-
229  {
-
230  FILE *state;
-
231  char filename[100];
-
232  long long int index;
-
233  sprintf(filename, "state_rank_%d.csv", qureg.chunkId);
-
234  state = fopen(filename, "w");
-
235  if (qureg.chunkId==0) fprintf(state, "real, imag\n");
-
236 
-
237  for(index=0; index<qureg.numAmpsPerChunk; index++){
-
238  # if QuEST_PREC==1 || QuEST_PREC==2
-
239  fprintf(state, "%.12f, %.12f\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
240  # elif QuEST_PREC == 4
-
241  fprintf(state, "%.12Lf, %.12Lf\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
-
242  #endif
-
243  }
-
244  fclose(state);
-
245 }
+

Definition at line 219 of file QuEST_common.c.

+
219  {
+
220  FILE *state;
+
221  char filename[100];
+
222  long long int index;
+
223  sprintf(filename, "state_rank_%d.csv", qureg.chunkId);
+
224  state = fopen(filename, "w");
+
225  if (qureg.chunkId==0) fprintf(state, "real, imag\n");
+
226 
+
227  for(index=0; index<qureg.numAmpsPerChunk; index++){
+
228  # if QuEST_PREC==1 || QuEST_PREC==2
+
229  fprintf(state, "%.12f, %.12f\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
230  # elif QuEST_PREC == 4
+
231  fprintf(state, "%.12Lf, %.12Lf\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
+
232  #endif
+
233  }
+
234  fclose(state);
+
235 }

References Qureg::chunkId, Qureg::numAmpsPerChunk, and Qureg::stateVec.

@@ -611,17 +684,17 @@

Author
Ania Brown
-

Definition at line 1579 of file QuEST.c.

-
1579  {
-
1580  statevec_reportStateToScreen(qureg, env, reportRank);
-
1581 }
+

Definition at line 1594 of file QuEST.c.

+
1594  {
+
1595  statevec_reportStateToScreen(qureg, env, reportRank);
+
1596 }
-

References statevec_reportStateToScreen().

+

References statevec_reportStateToScreen().

- -

◆ seedQuEST()

+ +

◆ seedQuEST()

@@ -629,6 +702,12 @@

void seedQuEST ( + QuESTEnv *  + env, + + + + unsigned long int *  seedArray, @@ -646,33 +725,59 @@

-

Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed.

-

This function uses the mt19937 init_by_array function with numSeeds keys supplied by the user. Subsequent calls to mt19937 genrand functions will use this seeding. For a multi process code, the same seed is given to all process, therefore this seeding is only appropriate to use for functions such as measure where all processes require the same random value.

-

For more information about the MT, see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html

+

Seeds the random number generator with a custom array of key(s), overriding the default keys.

+

This determines the sequence of outcomes in functions like measure() and measureWithStats().

+

In distributed mode, the key(s) passed to the master node will be broadcast to all other nodes, such that every node generates the same sequence of pseudorandom numbers.

+

This function will copy the contents of seedArray into a permanent array env.seeds, so seedArray is afterward safe to free.

+
+

QuEST uses the Mersenne Twister for random number generation.

+
+
See also
+
Parameters
+
[in]enva pointer to the QuESTEnv runtime environment
[in]seedArrayArray of integers to use as seed. This allows the MT to be initialised with more than a 32-bit integer if required
[in]numSeedsLength of seedArray
-
Author
Ania Brown
-

Seed the Mersenne Twister used for random number generation in the QuEST environment with a user defined seed.

- -

Definition at line 222 of file QuEST_common.c.

-
222  {
-
223  // init MT random number generator with user defined list of seeds
-
224  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
225  // used by the master process
-
226  init_by_array(seedArray, numSeeds);
-
227 }
+
Author
Ania Brown
+
+Tyson Jones (doc)
+ +

Definition at line 1388 of file QuEST_cpu_distributed.c.

+
1388  {
+
1389 
+
1390  // it is imperative every node agrees on the seed, so that random decisions
+
1391  // agree on every node. Hence we use only the master node keys.
+
1392  MPI_Bcast(seedArray, numSeeds, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
+
1393 
+
1394  // free existing seed array, if exists
+
1395  if (env->seeds != NULL)
+
1396  free(env->seeds);
+
1397 
+
1398  // record keys in permanent heap
+
1399  env->seeds = malloc(numSeeds * sizeof *(env->seeds));
+
1400  for (int i=0; i<numSeeds; i++)
+
1401  (env->seeds)[i] = seedArray[i];
+
1402  env->numSeeds = numSeeds;
+
1403 
+
1404  // pass keys to Mersenne Twister seeder
+
1405  init_by_array(seedArray, numSeeds);
+
1406 }
-

References init_by_array().

+

References init_by_array(), QuESTEnv::numSeeds, and QuESTEnv::seeds.

+ +

Referenced by seedQuESTDefault().

- -

◆ seedQuESTDefault()

+ +

◆ seedQuESTDefault()

@@ -680,46 +785,46 @@

void seedQuESTDefault ( - void  - ) + QuESTEnv *  + env)

-

Seed the Mersenne Twister used for random number generation in the QuEST environment with an example default seed.

-

This default seeding function uses the mt19937 init_by_array function with two keys – time and pid. Subsequent calls to mt19937 genrand functions will use this seeding. For a multi process code, the same seed is given to all process, therefore this seeding is only appropriate to use for functions such as measure where all processes require the same random value.

-

For more information about the MT, see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html

+

Seeds the random number generator with the (master node) current time and process ID.

+

This is the default seeding used by createQuESTEnv(), and determines the outcomes in functions like measure() and measureWithStats().

+

In distributed mode, every node agrees on the seed (nominated by the master node) such that every node generates the same sequence of pseudorandom numbers.

-

To manually generate a key to seed MT, use seedQuEST()

+

QuEST uses the Mersenne Twister for random number generation.

-

Presently, only the following functions involve random generation (through internal function generateMeasurementOutcome()):

See also
+
Parameters
+ + +
[in]enva pointer to the QuESTEnv runtime environment
+
+
Author
Ania Brown
-Balint Koczor (Windows compatibility)
- -

Definition at line 1384 of file QuEST_cpu_distributed.c.

-
1384  {
-
1385  // init MT random number generator with three keys -- time and pid
-
1386  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
-
1387  // used by the master process
-
1388 
-
1389  unsigned long int key[2];
- -
1391  // this seed will be used to generate the same random number on all procs,
-
1392  // therefore we want to make sure all procs receive the same key
-
1393  MPI_Bcast(key, 2, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
-
1394  init_by_array(key, 2);
-
1395 }
+Balint Koczor (Windows compatibility) +
+Tyson Jones (doc)
+ +

Definition at line 1614 of file QuEST.c.

+
1614  {
+
1615 
+
1616  // seed Mersenne Twister random number generator with two keys -- time and pid
+
1617  unsigned long int keys[2];
+
1618  getQuESTDefaultSeedKey(keys);
+
1619  seedQuEST(env, keys, 2);
+
1620 }
-

References getQuESTDefaultSeedKey(), and init_by_array().

+

References getQuESTDefaultSeedKey(), and seedQuEST().

Referenced by createQuESTEnv().

@@ -754,12 +859,12 @@

Author
Ania Brown
-

Definition at line 162 of file QuEST_cpu_distributed.c.

-

@@ -790,37 +895,41 @@

Returns
1 if all processes succeeded, 0 if any one process failed
Author
Ania Brown
-

Definition at line 166 of file QuEST_cpu_distributed.c.

-
166  {
-
167  int totalSuccess;
-
168  MPI_Allreduce(&successCode, &totalSuccess, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
-
169  return totalSuccess;
-
170 }
+

Definition at line 168 of file QuEST_cpu_distributed.c.

+
168  {
+
169  int totalSuccess;
+
170  MPI_Allreduce(&successCode, &totalSuccess, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
+
171  return totalSuccess;
+
172 }

void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
-
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:39
-
int rank
Definition: QuEST.h:363
+
void copyStateFromGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
Definition: QuEST_cpu.c:45
+
int rank
Definition: QuEST.h:364
+
int numSeeds
Definition: QuEST.h:367
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:338
void getQuESTDefaultSeedKey(unsigned long int *key)
Definition: QuEST_common.c:195
+
void getQuESTSeeds(QuESTEnv env, unsigned long int **seeds, int *numSeeds)
Obtain the seeds presently used in random number generation.
Definition: QuEST.c:1622
#define qreal
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:329
-
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
+
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:336
-
void exitWithError(const char *msg, const char *func)
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
-
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1428
-
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:36
-
int numRanks
Definition: QuEST.h:364
+
void statevec_reportStateToScreen(Qureg qureg, QuESTEnv env, int reportRank)
Print the current state vector of probability amplitudes for a set of qubits to standard out.
Definition: QuEST_cpu.c:1439
+
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:42
+
int numRanks
Definition: QuEST.h:365
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
-
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1646
-
void validatePauliHamil(PauliHamil hamil, const char *caller)
+
unsigned long int * seeds
Definition: QuEST.h:366
+
void statevec_initDebugState(Qureg qureg)
Initialise the state vector of probability amplitudes to an (unphysical) state with each component of...
Definition: QuEST_cpu.c:1657
+
void validatePauliHamil(PauliHamil hamil, const char *caller)
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
+
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
+
void default_invalidQuESTInputError(const char *errMsg, const char *errFunc)
diff --git a/docs/group__decoherence.html b/docs/group__decoherence.html index f9cc4778a..47ab1d6f9 100644 --- a/docs/group__decoherence.html +++ b/docs/group__decoherence.html @@ -27,7 +27,7 @@ @@ -170,16 +170,16 @@

Definition at line 1270 of file QuEST.c.

-
1270  {
-
1271  validateDensityMatrQureg(qureg, __func__);
-
1272  validateTarget(qureg, targetQubit, __func__);
-
1273  validateOneQubitDampingProb(prob, __func__);
-
1274 
-
1275  densmatr_mixDamping(qureg, targetQubit, prob);
-
1276 }
+

Definition at line 1283 of file QuEST.c.

+
1283  {
+
1284  validateDensityMatrQureg(qureg, __func__);
+
1285  validateTarget(qureg, targetQubit, __func__);
+
1286  validateOneQubitDampingProb(prob, __func__);
+
1287 
+
1288  densmatr_mixDamping(qureg, targetQubit, prob);
+
1289 }
-

References densmatr_mixDamping(), validateDensityMatrQureg(), validateOneQubitDampingProb(), and validateTarget().

+

References densmatr_mixDamping(), validateDensityMatrQureg(), validateOneQubitDampingProb(), and validateTarget().

Referenced by TEST_CASE().

@@ -248,17 +248,17 @@

Author
Tyson Jones
-

Definition at line 999 of file QuEST.c.

-
999  {
-
1000  validateDensityMatrQureg(combineQureg, __func__);
-
1001  validateDensityMatrQureg(otherQureg, __func__);
-
1002  validateMatchingQuregDims(combineQureg, otherQureg, __func__);
-
1003  validateProb(otherProb, __func__);
-
1004 
-
1005  densmatr_mixDensityMatrix(combineQureg, otherProb, otherQureg);
-
1006 }
+

Definition at line 1012 of file QuEST.c.

+
1012  {
+
1013  validateDensityMatrQureg(combineQureg, __func__);
+
1014  validateDensityMatrQureg(otherQureg, __func__);
+
1015  validateMatchingQuregDims(combineQureg, otherQureg, __func__);
+
1016  validateProb(otherProb, __func__);
+
1017 
+
1018  densmatr_mixDensityMatrix(combineQureg, otherProb, otherQureg);
+
1019 }
-

References densmatr_mixDensityMatrix(), validateDensityMatrQureg(), validateMatchingQuregDims(), and validateProb().

+

References densmatr_mixDensityMatrix(), validateDensityMatrQureg(), validateMatchingQuregDims(), and validateProb().

Referenced by TEST_CASE().

@@ -334,18 +334,18 @@

Definition at line 1237 of file QuEST.c.

-
1237  {
-
1238  validateDensityMatrQureg(qureg, __func__);
-
1239  validateTarget(qureg, targetQubit, __func__);
-
1240  validateOneQubitDephaseProb(prob, __func__);
-
1241 
-
1242  densmatr_mixDephasing(qureg, targetQubit, 2*prob);
-
1243  qasm_recordComment(qureg,
-
1244  "Here, a phase (Z) error occured on qubit %d with probability %g", targetQubit, prob);
-
1245 }
+

Definition at line 1250 of file QuEST.c.

+
1250  {
+
1251  validateDensityMatrQureg(qureg, __func__);
+
1252  validateTarget(qureg, targetQubit, __func__);
+
1253  validateOneQubitDephaseProb(prob, __func__);
+
1254 
+
1255  densmatr_mixDephasing(qureg, targetQubit, 2*prob);
+
1256  qasm_recordComment(qureg,
+
1257  "Here, a phase (Z) error occured on qubit %d with probability %g", targetQubit, prob);
+
1258 }
-

References densmatr_mixDephasing(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitDephaseProb(), and validateTarget().

+

References densmatr_mixDephasing(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitDephaseProb(), and validateTarget().

Referenced by TEST_CASE().

@@ -424,19 +424,19 @@

Definition at line 1259 of file QuEST.c.

-
1259  {
-
1260  validateDensityMatrQureg(qureg, __func__);
-
1261  validateTarget(qureg, targetQubit, __func__);
-
1262  validateOneQubitDepolProb(prob, __func__);
-
1263 
-
1264  densmatr_mixDepolarising(qureg, targetQubit, (4*prob)/3.0);
-
1265  qasm_recordComment(qureg,
-
1266  "Here, a homogeneous depolarising error (X, Y, or Z) occured on "
-
1267  "qubit %d with total probability %g", targetQubit, prob);
-
1268 }
+

Definition at line 1272 of file QuEST.c.

+
1272  {
+
1273  validateDensityMatrQureg(qureg, __func__);
+
1274  validateTarget(qureg, targetQubit, __func__);
+
1275  validateOneQubitDepolProb(prob, __func__);
+
1276 
+
1277  densmatr_mixDepolarising(qureg, targetQubit, (4*prob)/3.0);
+
1278  qasm_recordComment(qureg,
+
1279  "Here, a homogeneous depolarising error (X, Y, or Z) occured on "
+
1280  "qubit %d with total probability %g", targetQubit, prob);
+
1281 }
-

References densmatr_mixDepolarising(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitDepolProb(), and validateTarget().

+

References densmatr_mixDepolarising(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitDepolProb(), and validateTarget().

Referenced by TEST_CASE().

@@ -526,18 +526,18 @@

Definition at line 1301 of file QuEST.c.

-
1301  {
-
1302  validateDensityMatrQureg(qureg, __func__);
-
1303  validateTarget(qureg, target, __func__);
-
1304  validateOneQubitKrausMap(qureg, ops, numOps, __func__);
-
1305 
-
1306  densmatr_mixKrausMap(qureg, target, ops, numOps);
-
1307  qasm_recordComment(qureg,
-
1308  "Here, an undisclosed Kraus map was effected on qubit %d", target);
-
1309 }
+

Definition at line 1314 of file QuEST.c.

+
1314  {
+
1315  validateDensityMatrQureg(qureg, __func__);
+
1316  validateTarget(qureg, target, __func__);
+
1317  validateOneQubitKrausMap(qureg, ops, numOps, __func__);
+
1318 
+
1319  densmatr_mixKrausMap(qureg, target, ops, numOps);
+
1320  qasm_recordComment(qureg,
+
1321  "Here, an undisclosed Kraus map was effected on qubit %d", target);
+
1322 }
-

References densmatr_mixKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitKrausMap(), and validateTarget().

+

References densmatr_mixKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitKrausMap(), and validateTarget().

Referenced by TEST_CASE().

@@ -632,18 +632,18 @@

Definition at line 1321 of file QuEST.c.

-
1321  {
-
1322  validateDensityMatrQureg(qureg, __func__);
-
1323  validateMultiTargets(qureg, targets, numTargets, __func__);
-
1324  validateMultiQubitKrausMap(qureg, numTargets, ops, numOps, __func__);
-
1325 
-
1326  densmatr_mixMultiQubitKrausMap(qureg, targets, numTargets, ops, numOps);
-
1327  qasm_recordComment(qureg,
-
1328  "Here, an undisclosed %d-qubit Kraus map was applied to undisclosed qubits", numTargets);
-
1329 }
+

Definition at line 1334 of file QuEST.c.

+
1334  {
+
1335  validateDensityMatrQureg(qureg, __func__);
+
1336  validateMultiTargets(qureg, targets, numTargets, __func__);
+
1337  validateMultiQubitKrausMap(qureg, numTargets, ops, numOps, __func__);
+
1338 
+
1339  densmatr_mixMultiQubitKrausMap(qureg, targets, numTargets, ops, numOps);
+
1340  qasm_recordComment(qureg,
+
1341  "Here, an undisclosed %d-qubit Kraus map was applied to undisclosed qubits", numTargets);
+
1342 }
-

References densmatr_mixMultiQubitKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateMultiQubitKrausMap(), and validateMultiTargets().

+

References densmatr_mixMultiQubitKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateMultiQubitKrausMap(), and validateMultiTargets().

Referenced by TEST_CASE().

@@ -734,19 +734,19 @@

Definition at line 1290 of file QuEST.c.

-
1290  {
-
1291  validateDensityMatrQureg(qureg, __func__);
-
1292  validateTarget(qureg, qubit, __func__);
-
1293  validateOneQubitPauliProbs(probX, probY, probZ, __func__);
-
1294 
-
1295  densmatr_mixPauli(qureg, qubit, probX, probY, probZ);
-
1296  qasm_recordComment(qureg,
-
1297  "Here, X, Y and Z errors occured on qubit %d with probabilities "
-
1298  "%g, %g and %g respectively", qubit, probX, probY, probZ);
-
1299 }
+

Definition at line 1303 of file QuEST.c.

+
1303  {
+
1304  validateDensityMatrQureg(qureg, __func__);
+
1305  validateTarget(qureg, qubit, __func__);
+
1306  validateOneQubitPauliProbs(probX, probY, probZ, __func__);
+
1307 
+
1308  densmatr_mixPauli(qureg, qubit, probX, probY, probZ);
+
1309  qasm_recordComment(qureg,
+
1310  "Here, X, Y and Z errors occured on qubit %d with probabilities "
+
1311  "%g, %g and %g respectively", qubit, probX, probY, probZ);
+
1312 }
-

References densmatr_mixPauli(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitPauliProbs(), and validateTarget().

+

References densmatr_mixPauli(), qasm_recordComment(), validateDensityMatrQureg(), validateOneQubitPauliProbs(), and validateTarget().

Referenced by TEST_CASE().

@@ -825,20 +825,20 @@

Definition at line 1247 of file QuEST.c.

-
1247  {
-
1248  validateDensityMatrQureg(qureg, __func__);
-
1249  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
-
1250  validateTwoQubitDephaseProb(prob, __func__);
-
1251 
-
1252  ensureIndsIncrease(&qubit1, &qubit2);
-
1253  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, (4*prob)/3.0);
-
1254  qasm_recordComment(qureg,
-
1255  "Here, a phase (Z) error occured on either or both of qubits "
-
1256  "%d and %d with total probability %g", qubit1, qubit2, prob);
-
1257 }
+

Definition at line 1260 of file QuEST.c.

+
1260  {
+
1261  validateDensityMatrQureg(qureg, __func__);
+
1262  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
+
1263  validateTwoQubitDephaseProb(prob, __func__);
+
1264 
+
1265  ensureIndsIncrease(&qubit1, &qubit2);
+
1266  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, (4*prob)/3.0);
+
1267  qasm_recordComment(qureg,
+
1268  "Here, a phase (Z) error occured on either or both of qubits "
+
1269  "%d and %d with total probability %g", qubit1, qubit2, prob);
+
1270 }
-

References densmatr_mixTwoQubitDephasing(), ensureIndsIncrease(), qasm_recordComment(), validateDensityMatrQureg(), validateTwoQubitDephaseProb(), and validateUniqueTargets().

+

References densmatr_mixTwoQubitDephasing(), ensureIndsIncrease(), qasm_recordComment(), validateDensityMatrQureg(), validateTwoQubitDephaseProb(), and validateUniqueTargets().

Referenced by TEST_CASE().

@@ -925,20 +925,20 @@

Definition at line 1278 of file QuEST.c.

-
1278  {
-
1279  validateDensityMatrQureg(qureg, __func__);
-
1280  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
-
1281  validateTwoQubitDepolProb(prob, __func__);
-
1282 
-
1283  ensureIndsIncrease(&qubit1, &qubit2);
-
1284  densmatr_mixTwoQubitDepolarising(qureg, qubit1, qubit2, (16*prob)/15.0);
-
1285  qasm_recordComment(qureg,
-
1286  "Here, a homogeneous depolarising error occured on qubits %d and %d "
-
1287  "with total probability %g", qubit1, qubit2, prob);
-
1288 }
+

Definition at line 1291 of file QuEST.c.

+
1291  {
+
1292  validateDensityMatrQureg(qureg, __func__);
+
1293  validateUniqueTargets(qureg, qubit1, qubit2, __func__);
+
1294  validateTwoQubitDepolProb(prob, __func__);
+
1295 
+
1296  ensureIndsIncrease(&qubit1, &qubit2);
+
1297  densmatr_mixTwoQubitDepolarising(qureg, qubit1, qubit2, (16*prob)/15.0);
+
1298  qasm_recordComment(qureg,
+
1299  "Here, a homogeneous depolarising error occured on qubits %d and %d "
+
1300  "with total probability %g", qubit1, qubit2, prob);
+
1301 }
-

References densmatr_mixTwoQubitDepolarising(), ensureIndsIncrease(), qasm_recordComment(), validateDensityMatrQureg(), validateTwoQubitDepolProb(), and validateUniqueTargets().

+

References densmatr_mixTwoQubitDepolarising(), ensureIndsIncrease(), qasm_recordComment(), validateDensityMatrQureg(), validateTwoQubitDepolProb(), and validateUniqueTargets().

Referenced by TEST_CASE().

@@ -1030,51 +1030,51 @@

Definition at line 1311 of file QuEST.c.

-
1311  {
-
1312  validateDensityMatrQureg(qureg, __func__);
-
1313  validateMultiTargets(qureg, (int[]) {target1,target2}, 2, __func__);
-
1314  validateTwoQubitKrausMap(qureg, ops, numOps, __func__);
-
1315 
-
1316  densmatr_mixTwoQubitKrausMap(qureg, target1, target2, ops, numOps);
-
1317  qasm_recordComment(qureg,
-
1318  "Here, an undisclosed two-qubit Kraus map was effected on qubits %d and %d", target1, target2);
-
1319 }
+

Definition at line 1324 of file QuEST.c.

+
1324  {
+
1325  validateDensityMatrQureg(qureg, __func__);
+
1326  validateMultiTargets(qureg, (int[]) {target1,target2}, 2, __func__);
+
1327  validateTwoQubitKrausMap(qureg, ops, numOps, __func__);
+
1328 
+
1329  densmatr_mixTwoQubitKrausMap(qureg, target1, target2, ops, numOps);
+
1330  qasm_recordComment(qureg,
+
1331  "Here, an undisclosed two-qubit Kraus map was effected on qubits %d and %d", target1, target2);
+
1332 }
-

References densmatr_mixTwoQubitKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateMultiTargets(), and validateTwoQubitKrausMap().

+

References densmatr_mixTwoQubitKrausMap(), qasm_recordComment(), validateDensityMatrQureg(), validateMultiTargets(), and validateTwoQubitKrausMap().

Referenced by TEST_CASE().

-
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
-
void validateDensityMatrQureg(Qureg qureg, const char *caller)
-
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
-
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:654
-
void validateProb(qreal prob, const char *caller)
-
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:697
-
void validateTwoQubitDepolProb(qreal prob, const char *caller)
-
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:890
-
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:79
-
void validateOneQubitDephaseProb(qreal prob, const char *caller)
-
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
-
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
-
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
-
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:689
-
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
-
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
+
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
+
void validateDensityMatrQureg(Qureg qureg, const char *caller)
+
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
+
void densmatr_mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:644
+
void validateProb(qreal prob, const char *caller)
+
void densmatr_mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:701
+
void validateTwoQubitDepolProb(qreal prob, const char *caller)
+
void densmatr_mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Definition: QuEST_cpu.c:901
+
void densmatr_mixDephasing(Qureg qureg, int targetQubit, qreal dephase)
Definition: QuEST_cpu.c:85
+
void validateOneQubitDephaseProb(qreal prob, const char *caller)
+
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
+
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
+
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
+
void densmatr_mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:682
+
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
+
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
-
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
-
void validateOneQubitDepolProb(qreal prob, const char *caller)
-
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
-
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:730
-
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
+
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
+
void validateOneQubitDepolProb(qreal prob, const char *caller)
+
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
+
void densmatr_mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Definition: QuEST_common.c:743
+
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
void ensureIndsIncrease(int *ind1, int *ind2)
Definition: QuEST_common.c:70
-
void validateOneQubitDampingProb(qreal prob, const char *caller)
-
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
-
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
-
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
+
void validateOneQubitDampingProb(qreal prob, const char *caller)
+
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
+
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
+
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)

diff --git a/docs/group__init.html b/docs/group__init.html index 95b537968..d11df45a2 100644 --- a/docs/group__init.html +++ b/docs/group__init.html @@ -27,7 +27,7 @@ @@ -78,7 +78,7 @@  Initialise qureg into to a given pure state of an equivalent Hilbert dimension. More...
  void initStateFromAmps (Qureg qureg, qreal *reals, qreal *imags) - Initialise state-vector qureg by specifying all amplitudes. More...
+ Initialise qureg by specifying all amplitudes. More...
  void initZeroState (Qureg qureg)  Initialise qureg into the zero state. More...
@@ -146,15 +146,15 @@

Author
Tyson Jones
-

Definition at line 165 of file QuEST.c.

-
165  {
-
166  validateMatchingQuregTypes(targetQureg, copyQureg, __func__);
-
167  validateMatchingQuregDims(targetQureg, copyQureg, __func__);
-
168 
-
169  statevec_cloneQureg(targetQureg, copyQureg);
-
170 }
+

Definition at line 164 of file QuEST.c.

+
164  {
+
165  validateMatchingQuregTypes(targetQureg, copyQureg, __func__);
+
166  validateMatchingQuregDims(targetQureg, copyQureg, __func__);
+
167 
+
168  statevec_cloneQureg(targetQureg, copyQureg);
+
169 }
-

References statevec_cloneQureg(), validateMatchingQuregDims(), and validateMatchingQuregTypes().

+

References statevec_cloneQureg(), validateMatchingQuregDims(), and validateMatchingQuregTypes().

Referenced by TEST_CASE().

@@ -193,7 +193,7 @@

122  qasm_recordComment(qureg, "Here, the register was initialised to an unphysical all-zero-amplitudes 'state'.");

123 }

-

References qasm_recordComment(), and statevec_initBlankState().

+

References qasm_recordComment(), and statevec_initBlankState().

Referenced by TEST_CASE().

@@ -267,7 +267,7 @@

142  qasm_recordInitClassical(qureg, stateInd);

143 }

-

References densmatr_initClassicalState(), Qureg::isDensityMatrix, qasm_recordInitClassical(), statevec_initClassicalState(), and validateStateIndex().

+

References densmatr_initClassicalState(), Qureg::isDensityMatrix, qasm_recordInitClassical(), statevec_initClassicalState(), and validateStateIndex().

Referenced by TEST_CASE().

@@ -316,7 +316,7 @@

131  qasm_recordInitPlus(qureg);

132 }

-

References densmatr_initPlusState(), Qureg::isDensityMatrix, qasm_recordInitPlus(), and statevec_initPlusState().

+

References densmatr_initPlusState(), Qureg::isDensityMatrix, qasm_recordInitPlus(), and statevec_initPlusState().

Referenced by TEST_CASE().

@@ -388,7 +388,7 @@

154  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");

155 }

-

References densmatr_initPureState(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_cloneQureg(), validateMatchingQuregDims(), and validateSecondQuregStateVec().

+

References densmatr_initPureState(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_cloneQureg(), validateMatchingQuregDims(), and validateSecondQuregStateVec().

Referenced by TEST_CASE().

@@ -426,9 +426,10 @@

-

Initialise state-vector qureg by specifying all amplitudes.

+

Initialise qureg by specifying all amplitudes.

+

For density matrices, it is assumed the amplitudes have been flattened column-wise into the given arrays.

The real and imaginary components of the amplitudes are passed in separate arrays, reals and imags, each of which must have length qureg.numAmpsTotal. There is no automatic checking that the passed arrays are L2 normalised, so this can be used to prepare qureg in a non-physical state.

-

In distributed mode, this would require the complete state-vector to fit in every node. To manually prepare a state-vector which cannot fit in every node, use setAmps()

+

In distributed mode, this would require the complete state to fit in every node. To manually prepare a state for which all amplitudes cannot fit into a single node, use setAmps()

See also
@@ -443,10 +444,6 @@

Exceptions
- + + + @@ -181,19 +184,19 @@

Author
Tyson Jones
-

Definition at line 1114 of file QuEST.c.

-
1114  {
-
1115  validateDiagonalOp(qureg, op, __func__);
-
1116 
-
1117  if (qureg.isDensityMatrix)
-
1118  densmatr_applyDiagonalOp(qureg, op);
-
1119  else
-
1120  statevec_applyDiagonalOp(qureg, op);
-
1121 
-
1122  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
-
1123 }
+

Definition at line 1127 of file QuEST.c.

+
1127  {
+
1128  validateDiagonalOp(qureg, op, __func__);
+
1129 
+
1130  if (qureg.isDensityMatrix)
+
1131  densmatr_applyDiagonalOp(qureg, op);
+
1132  else
+
1133  statevec_applyDiagonalOp(qureg, op);
+
1134 
+
1135  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
+
1136 }
-

References densmatr_applyDiagonalOp(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_applyDiagonalOp(), and validateDiagonalOp().

+

References densmatr_applyDiagonalOp(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_applyDiagonalOp(), and validateDiagonalOp().

Referenced by TEST_CASE().

@@ -249,20 +252,20 @@

Author
Tyson Jones
-

Definition at line 877 of file QuEST.c.

-
877  {
-
878 
-
879  qasm_recordComment(qureg, "Beginning of QFT circuit");
-
880 
-
881  int qubits[qureg.numQubitsRepresented];
-
882  for (int i=0; i<qureg.numQubitsRepresented; i++)
-
883  qubits[i] = i;
-
884  agnostic_applyQFT(qureg, qubits, qureg.numQubitsRepresented);
-
885 
-
886  qasm_recordComment(qureg, "End of QFT circuit");
-
887 }
+

Definition at line 876 of file QuEST.c.

+
876  {
+
877 
+
878  qasm_recordComment(qureg, "Beginning of QFT circuit");
+
879 
+
880  int qubits[100];
+
881  for (int i=0; i<qureg.numQubitsRepresented; i++)
+
882  qubits[i] = i;
+
883  agnostic_applyQFT(qureg, qubits, qureg.numQubitsRepresented);
+
884 
+
885  qasm_recordComment(qureg, "End of QFT circuit");
+
886 }
-

References agnostic_applyQFT(), Qureg::numQubitsRepresented, and qasm_recordComment().

+

References agnostic_applyQFT(), Qureg::numQubitsRepresented, and qasm_recordComment().

Referenced by TEST_CASE().

@@ -329,17 +332,17 @@

Author
Tyson Jones
-

Definition at line 1071 of file QuEST.c.

-
1071  {
-
1072  validateTarget(qureg, targetQubit, __func__);
-
1073 
-
1074  // actually just left-multiplies any complex matrix
-
1075  statevec_unitary(qureg, targetQubit, u);
-
1076 
-
1077  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
-
1078 }
+

Definition at line 1084 of file QuEST.c.

+
1084  {
+
1085  validateTarget(qureg, targetQubit, __func__);
+
1086 
+
1087  // actually just left-multiplies any complex matrix
+
1088  statevec_unitary(qureg, targetQubit, u);
+
1089 
+
1090  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
+
1091 }
-

References qasm_recordComment(), statevec_unitary(), and validateTarget().

+

References qasm_recordComment(), statevec_unitary(), and validateTarget().

Referenced by TEST_CASE().

@@ -421,18 +424,18 @@

Author
Tyson Jones
-

Definition at line 1080 of file QuEST.c.

-
1080  {
-
1081  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
-
1082  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
-
1083 
-
1084  // actually just left-multiplies any complex matrix
-
1085  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
-
1086 
-
1087  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
-
1088 }
+

Definition at line 1093 of file QuEST.c.

+
1093  {
+
1094  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
+
1095  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
+
1096 
+
1097  // actually just left-multiplies any complex matrix
+
1098  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
+
1099 
+
1100  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
+
1101 }
-

References qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiQubitMatrixFitsInNode(), and validateMultiTargets().

+

References qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiQubitMatrixFitsInNode(), and validateMultiTargets().

Referenced by TEST_CASE().

@@ -516,19 +519,19 @@

Author
Tyson Jones
-

Definition at line 1090 of file QuEST.c.

-
1090  {
-
1091  validateMultiTargets(qureg, targs, numTargs, __func__);
-
1092  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
-
1093 
-
1094  // actually just left-multiplies any complex matrix
-
1095  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
-
1096 
-
1097  int dim = (1 << numTargs);
-
1098  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
-
1099 }
+

Definition at line 1103 of file QuEST.c.

+
1103  {
+
1104  validateMultiTargets(qureg, targs, numTargs, __func__);
+
1105  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
+
1106 
+
1107  // actually just left-multiplies any complex matrix
+
1108  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
+
1109 
+
1110  int dim = (1 << numTargs);
+
1111  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
+
1112 }
-

References qasm_recordComment(), statevec_multiQubitUnitary(), validateMultiQubitMatrix(), and validateMultiTargets().

+

References qasm_recordComment(), statevec_multiQubitUnitary(), validateMultiQubitMatrix(), and validateMultiTargets().

Referenced by TEST_CASE().

@@ -620,21 +623,21 @@

Author
Tyson Jones
-

Definition at line 1101 of file QuEST.c.

-
1101  {
-
1102  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
-
1103  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
-
1104 
-
1105  // actually just left-multiplies any complex matrix
-
1106  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
-
1107  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
-
1108 
-
1109  int numTot = numTargs + numCtrls;
-
1110  int dim = (1 << numTot );
-
1111  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
-
1112 }
+

Definition at line 1114 of file QuEST.c.

+
1114  {
+
1115  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
+
1116  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
+
1117 
+
1118  // actually just left-multiplies any complex matrix
+
1119  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
+
1120  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
+
1121 
+
1122  int numTot = numTargs + numCtrls;
+
1123  int dim = (1 << numTot );
+
1124  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
+
1125 }
-

References getQubitBitMask(), qasm_recordComment(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitMatrix().

+

References getQubitBitMask(), qasm_recordComment(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitMatrix().

Referenced by TEST_CASE().

@@ -822,25 +825,25 @@

Author
Tyson Jones
-

Definition at line 762 of file QuEST.c.

-
762  {
-
763  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
764  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
765  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
-
766 
-
767  int conj = 0;
-
768  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
-
769  if (qureg.isDensityMatrix) {
-
770  conj = 1;
-
771  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
772  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
-
773  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
774  }
-
775 
-
776  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0);
-
777 }
+

Definition at line 761 of file QuEST.c.

+
761  {
+
762  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
763  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
764  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
+
765 
+
766  int conj = 0;
+
767  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
+
768  if (qureg.isDensityMatrix) {
+
769  conj = 1;
+
770  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
771  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
+
772  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
773  }
+
774 
+
775  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0);
+
776 }
-

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiVarPhaseFunc(), shiftSubregIndices(), statevec_applyMultiVarPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncTerms(), and validateQubitSubregs().

+

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiVarPhaseFunc(), shiftSubregIndices(), statevec_applyMultiVarPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncTerms(), and validateQubitSubregs().

Referenced by TEST_CASE().

@@ -998,26 +1001,26 @@

Author
Tyson Jones
-

Definition at line 779 of file QuEST.c.

-
779  {
-
780  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
781  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
782  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
-
783  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
-
784 
-
785  int conj = 0;
-
786  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
-
787  if (qureg.isDensityMatrix) {
-
788  conj = 1;
-
789  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
790  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
-
791  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
792  }
-
793 
-
794  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides);
-
795 }
+

Definition at line 778 of file QuEST.c.

+
778  {
+
779  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
780  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
781  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
+
782  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
+
783 
+
784  int conj = 0;
+
785  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
+
786  if (qureg.isDensityMatrix) {
+
787  conj = 1;
+
788  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
789  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
+
790  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
791  }
+
792 
+
793  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides);
+
794 }
-

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiVarPhaseFunc(), shiftSubregIndices(), statevec_applyMultiVarPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validateMultiVarPhaseFuncTerms(), and validateQubitSubregs().

+

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiVarPhaseFunc(), shiftSubregIndices(), statevec_applyMultiVarPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validateMultiVarPhaseFuncTerms(), and validateQubitSubregs().

Referenced by TEST_CASE().

@@ -1175,25 +1178,25 @@

Author
Tyson Jones
-

Definition at line 797 of file QuEST.c.

-
797  {
-
798  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
799  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
800  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
-
801 
-
802  int conj = 0;
-
803  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
-
804  if (qureg.isDensityMatrix) {
-
805  conj = 1;
-
806  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
807  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
-
808  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
809  }
-
810 
-
811  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0);
-
812 }
+

Definition at line 796 of file QuEST.c.

+
796  {
+
797  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
798  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
799  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
+
800 
+
801  int conj = 0;
+
802  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
+
803  if (qureg.isDensityMatrix) {
+
804  conj = 1;
+
805  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
806  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
+
807  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
808  }
+
809 
+
810  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0);
+
811 }
-

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validatePhaseFuncName(), and validateQubitSubregs().

+

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validatePhaseFuncName(), and validateQubitSubregs().

Referenced by TEST_CASE().

@@ -1336,26 +1339,26 @@

Author
Tyson Jones
-

Definition at line 814 of file QuEST.c.

-
814  {
-
815  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
-
816  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
-
817  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
-
818  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
-
819 
-
820  int conj = 0;
-
821  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
-
822  if (qureg.isDensityMatrix) {
-
823  conj = 1;
-
824  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
-
825  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
-
826  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
-
827  }
-
828 
-
829  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides);
-
830 }
+

Definition at line 813 of file QuEST.c.

+
813  {
+
814  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
+
815  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
+
816  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
+
817  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
+
818 
+
819  int conj = 0;
+
820  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
+
821  if (qureg.isDensityMatrix) {
+
822  conj = 1;
+
823  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
+
824  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
+
825  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
+
826  }
+
827 
+
828  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides);
+
829 }
-

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validatePhaseFuncName(), and validateQubitSubregs().

+

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validatePhaseFuncName(), and validateQubitSubregs().

Referenced by TEST_CASE().

@@ -1444,6 +1447,9 @@

invokes phase function

\[ f(\vec{r}, \theta)|_{\theta=0.5} \; = \; \begin{cases} \pi & \;\;\; \vec{r}=\vec{0} \\ \displaystyle 0.5 \left[ \sum_j^{\text{numRegs}} {r_j}^2 \right]^{-1/2} & \;\;\;\text{otherwise} \end{cases}. \]

+

Notice the order of the parameters matches the order of the words in the phaseFunc.

+

Functions SCALED_INVERSE_SHIFTED_NORM and SCALED_INVERSE_SHIFTED_DISTANCE, which can have denominators arbitrarily close to zero, will invoke the divergence parameter whenever the denominator is smaller than (or equal to) machine precision REAL_EPS.

+
  • Functions allowing the shifting of sub-register values, which are SCALED_INVERSE_SHIFTED_NORM and SCALED_INVERSE_SHIFTED_DISTANCE, need these shift values to be passed in the params argument after the scaling and divergence override parameters listed above. The function SCALED_INVERSE_SHIFTED_NORM needs as many extra parameters, as there are sub-registers; SCALED_INVERSE_SHIFTED_DISTANCE needs one extra parameter for each pair of sub-registers. For example,

    int qubits[] = {0,1,2,3, 4,5,6,7};
    @@ -1518,25 +1524,25 @@

    Definition at line 832 of file QuEST.c.

    -
    832  {
    -
    833  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
    -
    834  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
    -
    835  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
    -
    836 
    -
    837  int conj = 0;
    -
    838  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
    -
    839  if (qureg.isDensityMatrix) {
    -
    840  conj = 1;
    -
    841  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
    -
    842  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
    -
    843  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
    -
    844  }
    -
    845 
    -
    846  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0);
    -
    847 }
    +

    Definition at line 831 of file QuEST.c.

    +
    831  {
    +
    832  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
    +
    833  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
    +
    834  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
    +
    835 
    +
    836  int conj = 0;
    +
    837  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
    +
    838  if (qureg.isDensityMatrix) {
    +
    839  conj = 1;
    +
    840  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
    +
    841  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
    +
    842  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
    +
    843  }
    +
    844 
    +
    845  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0);
    +
    846 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validatePhaseFuncName(), and validateQubitSubregs().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validatePhaseFuncName(), and validateQubitSubregs().

    Referenced by TEST_CASE().

    @@ -1692,28 +1698,28 @@

    Author
    Tyson Jones
    -

    Definition at line 849 of file QuEST.c.

    -
    849  {
    -
    850  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
    -
    851  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
    -
    852  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
    -
    853  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
    -
    854 
    -
    855  int conj = 0;
    -
    856  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
    -
    857  if (qureg.isDensityMatrix) {
    -
    858  conj = 1;
    -
    859  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
    -
    860  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
    -
    861  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
    -
    862  }
    -
    863 
    -
    864  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    865 }
    +

    Definition at line 848 of file QuEST.c.

    +
    848  {
    +
    849  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
    +
    850  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
    +
    851  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
    +
    852  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
    +
    853 
    +
    854  int conj = 0;
    +
    855  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
    +
    856  if (qureg.isDensityMatrix) {
    +
    857  conj = 1;
    +
    858  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
    +
    859  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
    +
    860  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
    +
    861  }
    +
    862 
    +
    863  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    864 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validatePhaseFuncName(), and validateQubitSubregs().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validatePhaseFuncName(), and validateQubitSubregs().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -1784,21 +1790,21 @@

    Author
    Tyson Jones
    -

    Definition at line 1046 of file QuEST.c.

    -
    1046  {
    -
    1047  validateMatchingQuregTypes(inQureg, outQureg, __func__);
    -
    1048  validateMatchingQuregDims(inQureg, outQureg, __func__);
    -
    1049  validatePauliHamil(hamil, __func__);
    -
    1050  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
    -
    1051 
    -
    1052  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
    -
    1053 
    -
    1054  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
    -
    1055 }
    +

    Definition at line 1059 of file QuEST.c.

    +
    1059  {
    +
    1060  validateMatchingQuregTypes(inQureg, outQureg, __func__);
    +
    1061  validateMatchingQuregDims(inQureg, outQureg, __func__);
    +
    1062  validatePauliHamil(hamil, __func__);
    +
    1063  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
    +
    1064 
    +
    1065  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
    +
    1066 
    +
    1067  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
    +
    1068 }
    -

    References PauliHamil::numSumTerms, PauliHamil::pauliCodes, qasm_recordComment(), statevec_applyPauliSum(), PauliHamil::termCoeffs, validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), and validatePauliHamil().

    +

    References PauliHamil::numSumTerms, PauliHamil::pauliCodes, qasm_recordComment(), statevec_applyPauliSum(), PauliHamil::termCoeffs, validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), and validatePauliHamil().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -1884,21 +1890,21 @@

    Author
    Tyson Jones
    -

    Definition at line 1035 of file QuEST.c.

    -
    1035  {
    -
    1036  validateMatchingQuregTypes(inQureg, outQureg, __func__);
    -
    1037  validateMatchingQuregDims(inQureg, outQureg, __func__);
    -
    1038  validateNumPauliSumTerms(numSumTerms, __func__);
    -
    1039  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
    -
    1040 
    -
    1041  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
    -
    1042 
    -
    1043  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
    -
    1044 }
    +

    Definition at line 1048 of file QuEST.c.

    +
    1048  {
    +
    1049  validateMatchingQuregTypes(inQureg, outQureg, __func__);
    +
    1050  validateMatchingQuregDims(inQureg, outQureg, __func__);
    +
    1051  validateNumPauliSumTerms(numSumTerms, __func__);
    +
    1052  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
    +
    1053 
    +
    1054  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
    +
    1055 
    +
    1056  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
    +
    1057 }
    -

    References Qureg::numQubitsRepresented, qasm_recordComment(), statevec_applyPauliSum(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateNumPauliSumTerms(), and validatePauliCodes().

    +

    References Qureg::numQubitsRepresented, qasm_recordComment(), statevec_applyPauliSum(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateNumPauliSumTerms(), and validatePauliCodes().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

  • @@ -2045,27 +2051,27 @@

    Author
    Tyson Jones
    -

    Definition at line 727 of file QuEST.c.

    -
    727  {
    -
    728  validateMultiQubits(qureg, qubits, numQubits, __func__);
    -
    729  validateBitEncoding(numQubits, encoding, __func__);
    -
    730  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, NULL, 0, __func__);
    -
    731 
    -
    732  int conj = 0;
    -
    733  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
    -
    734  if (qureg.isDensityMatrix) {
    -
    735  conj = 1;
    -
    736  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
    -
    737  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
    -
    738  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
    -
    739  }
    -
    740 
    -
    741  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0);
    -
    742 }
    +

    Definition at line 726 of file QuEST.c.

    +
    726  {
    +
    727  validateMultiQubits(qureg, qubits, numQubits, __func__);
    +
    728  validateBitEncoding(numQubits, encoding, __func__);
    +
    729  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, NULL, 0, __func__);
    +
    730 
    +
    731  int conj = 0;
    +
    732  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
    +
    733  if (qureg.isDensityMatrix) {
    +
    734  conj = 1;
    +
    735  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
    +
    736  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
    +
    737  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
    +
    738  }
    +
    739 
    +
    740  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0);
    +
    741 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordPhaseFunc(), shiftIndices(), statevec_applyPhaseFuncOverrides(), validateBitEncoding(), validateMultiQubits(), and validatePhaseFuncTerms().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordPhaseFunc(), shiftIndices(), statevec_applyPhaseFuncOverrides(), validateBitEncoding(), validateMultiQubits(), and validatePhaseFuncTerms().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -2234,28 +2240,108 @@

    Author
    Tyson Jones
    -

    Definition at line 744 of file QuEST.c.

    -
    744  {
    -
    745  validateMultiQubits(qureg, qubits, numQubits, __func__);
    -
    746  validateBitEncoding(numQubits, encoding, __func__);
    -
    747  validatePhaseFuncOverrides(numQubits, encoding, overrideInds, numOverrides, __func__);
    -
    748  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, overrideInds, numOverrides, __func__);
    -
    749 
    -
    750  int conj = 0;
    -
    751  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
    -
    752  if (qureg.isDensityMatrix) {
    -
    753  conj = 1;
    -
    754  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
    -
    755  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
    -
    756  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
    -
    757  }
    -
    758 
    -
    759  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides);
    -
    760 }
    +

    Definition at line 743 of file QuEST.c.

    +
    743  {
    +
    744  validateMultiQubits(qureg, qubits, numQubits, __func__);
    +
    745  validateBitEncoding(numQubits, encoding, __func__);
    +
    746  validatePhaseFuncOverrides(numQubits, encoding, overrideInds, numOverrides, __func__);
    +
    747  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, overrideInds, numOverrides, __func__);
    +
    748 
    +
    749  int conj = 0;
    +
    750  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
    +
    751  if (qureg.isDensityMatrix) {
    +
    752  conj = 1;
    +
    753  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
    +
    754  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
    +
    755  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
    +
    756  }
    +
    757 
    +
    758  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides);
    +
    759 }
    +
    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordPhaseFunc(), shiftIndices(), statevec_applyPhaseFuncOverrides(), validateBitEncoding(), validateMultiQubits(), validatePhaseFuncOverrides(), and validatePhaseFuncTerms().

    + +

    Referenced by TEST_CASE().

    + +
    +

    + +

    ◆ applyProjector()

    + +
    +
    +

    invalidQuESTInputError()
      -
    • if qureg is not a state-vector (i.e. is a density matrix)
    • -
    -
    segmentation-fault
    • if either reals or imags have fewer than qureg.numAmpsTotal elements
    @@ -458,14 +455,13 @@

    Definition at line 157 of file QuEST.c.

    157  {
    -
    158  validateStateVecQureg(qureg, __func__);
    -
    159 
    -
    160  statevec_setAmps(qureg, 0, reals, imags, qureg.numAmpsTotal);
    -
    161 
    -
    162  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
    -
    163 }
    +
    158 
    +
    159  statevec_setAmps(qureg, 0, reals, imags, qureg.numAmpsTotal);
    +
    160 
    +
    161  qasm_recordComment(qureg, "Here, the register was initialised to an undisclosed given pure state.");
    +
    162 }
    -

    References Qureg::numAmpsTotal, qasm_recordComment(), statevec_setAmps(), and validateStateVecQureg().

    +

    References Qureg::numAmpsTotal, qasm_recordComment(), and statevec_setAmps().

    Referenced by TEST_CASE().

    @@ -507,7 +503,7 @@

    116  qasm_recordInitZero(qureg);
    117 }
    -

    References qasm_recordInitZero(), and statevec_initZeroState().

    +

    References qasm_recordInitZero(), and statevec_initZeroState().

    Referenced by createDensityQureg(), createQureg(), and TEST_CASE().

    @@ -577,7 +573,7 @@

    See also
    @@ -605,19 +601,19 @@

    Author
    Tyson Jones
    -

    Definition at line 1008 of file QuEST.c.

    -
    1008  {
    -
    1009  validateStateVecQureg(qureg, __func__);
    -
    1010  validateNumAmps(qureg, startInd, numAmps, __func__);
    -
    1011 
    -
    1012  statevec_setAmps(qureg, startInd, reals, imags, numAmps);
    -
    1013 
    -
    1014  qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
    -
    1015 }
    +

    Definition at line 1021 of file QuEST.c.

    +
    1021  {
    +
    1022  validateStateVecQureg(qureg, __func__);
    +
    1023  validateNumAmps(qureg, startInd, numAmps, __func__);
    +
    1024 
    +
    1025  statevec_setAmps(qureg, startInd, reals, imags, numAmps);
    +
    1026 
    +
    1027  qasm_recordComment(qureg, "Here, some amplitudes in the statevector were manually edited.");
    +
    1028 }
    -

    References qasm_recordComment(), statevec_setAmps(), validateNumAmps(), and validateStateVecQureg().

    +

    References qasm_recordComment(), statevec_setAmps(), validateNumAmps(), and validateStateVecQureg().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -697,52 +693,52 @@

    Author
    Tyson Jones
    -

    Definition at line 1024 of file QuEST.c.

    -
    1024  {
    -
    1025  validateMatchingQuregTypes(qureg1, qureg2, __func__);
    -
    1026  validateMatchingQuregTypes(qureg1, out, __func__);
    -
    1027  validateMatchingQuregDims(qureg1, qureg2, __func__);
    -
    1028  validateMatchingQuregDims(qureg1, out, __func__);
    -
    1029 
    -
    1030  statevec_setWeightedQureg(fac1, qureg1, fac2, qureg2, facOut, out);
    -
    1031 
    -
    1032  qasm_recordComment(out, "Here, the register was modified to an undisclosed and possibly unphysical state (setWeightedQureg).");
    -
    1033 }
    +

    Definition at line 1037 of file QuEST.c.

    +
    1037  {
    +
    1038  validateMatchingQuregTypes(qureg1, qureg2, __func__);
    +
    1039  validateMatchingQuregTypes(qureg1, out, __func__);
    +
    1040  validateMatchingQuregDims(qureg1, qureg2, __func__);
    +
    1041  validateMatchingQuregDims(qureg1, out, __func__);
    +
    1042 
    +
    1043  statevec_setWeightedQureg(fac1, qureg1, fac2, qureg2, facOut, out);
    +
    1044 
    +
    1045  qasm_recordComment(out, "Here, the register was modified to an undisclosed and possibly unphysical state (setWeightedQureg).");
    +
    1046 }
    -

    References qasm_recordComment(), statevec_setWeightedQureg(), validateMatchingQuregDims(), and validateMatchingQuregTypes().

    +

    References qasm_recordComment(), statevec_setWeightedQureg(), validateMatchingQuregDims(), and validateMatchingQuregTypes().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    -
    void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
    -
    void densmatr_initPlusState(Qureg targetQureg)
    Definition: QuEST_cpu.c:1154
    -
    void validateStateVecQureg(Qureg qureg, const char *caller)
    +
    void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
    +
    void densmatr_initPlusState(Qureg targetQureg)
    Definition: QuEST_cpu.c:1165
    +
    void validateStateVecQureg(Qureg qureg, const char *caller)
    void qasm_recordInitZero(Qureg qureg)
    Definition: QuEST_qasm.c:428
    -
    void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
    +
    void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
    void qasm_recordInitPlus(Qureg qureg)
    Definition: QuEST_qasm.c:443
    -
    void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
    Definition: QuEST_cpu.c:1115
    +
    void densmatr_initClassicalState(Qureg qureg, long long int stateInd)
    Definition: QuEST_cpu.c:1126
    #define qreal
    -
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
    Definition: QuEST.c:1008
    -
    void statevec_initZeroState(Qureg qureg)
    Definition: QuEST_cpu.c:1483
    -
    void statevec_initBlankState(Qureg qureg)
    Definition: QuEST_cpu.c:1453
    +
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
    Definition: QuEST.c:1021
    +
    void statevec_initZeroState(Qureg qureg)
    Definition: QuEST_cpu.c:1494
    +
    void statevec_initBlankState(Qureg qureg)
    Definition: QuEST_cpu.c:1464
    void qasm_recordInitClassical(Qureg qureg, long long int stateInd)
    Definition: QuEST_qasm.c:471
    -
    void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Definition: QuEST_cpu.c:1237
    -
    void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
    works for both statevectors and density matrices
    Definition: QuEST_cpu.c:1561
    -
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    void statevec_initPlusState(Qureg qureg)
    Definition: QuEST_cpu.c:1493
    +
    void statevec_setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Definition: QuEST_cpu.c:1248
    +
    void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
    works for both statevectors and density matrices
    Definition: QuEST_cpu.c:1572
    +
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    +
    void statevec_initPlusState(Qureg qureg)
    Definition: QuEST_cpu.c:1504
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:121
    void initClassicalState(Qureg qureg, long long int stateInd)
    Initialise qureg into the classical state (also known as a "computational basis state") with index st...
    Definition: QuEST.c:134
    -
    void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Definition: QuEST_cpu.c:3965
    +
    void statevec_setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Definition: QuEST_cpu.c:4005
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    void statevec_initClassicalState(Qureg qureg, long long int stateInd)
    Definition: QuEST_cpu.c:1525
    +
    void statevec_initClassicalState(Qureg qureg, long long int stateInd)
    Definition: QuEST_cpu.c:1536
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    -
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    -
    void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
    +
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    +
    void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
    long long int numAmpsTotal
    Total number of amplitudes, which are possibly distributed among machines.
    Definition: QuEST.h:334
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
    +
    void densmatr_initPureState(Qureg targetQureg, Qureg copyQureg)
    diff --git a/docs/group__normgate.html b/docs/group__normgate.html index 2b87f87b4..e357c063f 100644 --- a/docs/group__normgate.html +++ b/docs/group__normgate.html @@ -27,7 +27,7 @@ @@ -108,11 +108,13 @@

    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1), and returns the probability of such a measurement outcome.

    -

    This is effectively performing a projection, or a measurement with a forced outcome. This is an irreversible change to the state, whereby computational states inconsistant with the outcome are given zero amplitude and the qureg is renormalised. Exits with error if the given outcome has a near zero probability, and so cannot be collapsed into.

    +

    This is effectively performing a renormalising projection, or a measurement with a forced outcome. This is an irreversible change to the state, whereby computational states inconsistant with the outcome are given zero amplitude and the qureg is renormalised. The given outcome must not have a near zero probability, else it cannot be collapsed into.

    Note that the collapse probably used for renormalisation is calculated for outcome = 0, and assumed 1 minus this probability if outcome = 1. Hence this routine will not correctly project un-normalised quregs onto outcome = 1.

    +

    To avoid renormalisation after projection, or force projection into non-physical states with very small probability, use applyProjector().

    See also
    Parameters
    @@ -139,27 +141,27 @@

    Definition at line 953 of file QuEST.c.

    -
    953  {
    -
    954  validateTarget(qureg, measureQubit, __func__);
    -
    955  validateOutcome(outcome, __func__);
    -
    956 
    -
    957  qreal outcomeProb;
    -
    958  if (qureg.isDensityMatrix) {
    -
    959  outcomeProb = densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
    -
    960  validateMeasurementProb(outcomeProb, __func__);
    -
    961  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
    -
    962  } else {
    -
    963  outcomeProb = statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
    -
    964  validateMeasurementProb(outcomeProb, __func__);
    -
    965  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
    -
    966  }
    -
    967 
    -
    968  qasm_recordMeasurement(qureg, measureQubit);
    -
    969  return outcomeProb;
    -
    970 }
    +

    Definition at line 966 of file QuEST.c.

    +
    966  {
    +
    967  validateTarget(qureg, measureQubit, __func__);
    +
    968  validateOutcome(outcome, __func__);
    +
    969 
    +
    970  qreal outcomeProb;
    +
    971  if (qureg.isDensityMatrix) {
    +
    972  outcomeProb = densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
    +
    973  validateMeasurementProb(outcomeProb, __func__);
    +
    974  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
    +
    975  } else {
    +
    976  outcomeProb = statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
    +
    977  validateMeasurementProb(outcomeProb, __func__);
    +
    978  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, outcomeProb);
    +
    979  }
    +
    980 
    +
    981  qasm_recordMeasurement(qureg, measureQubit);
    +
    982  return outcomeProb;
    +
    983 }
    -

    References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), Qureg::isDensityMatrix, qasm_recordMeasurement(), qreal, statevec_calcProbOfOutcome(), statevec_collapseToKnownProbOutcome(), validateMeasurementProb(), validateOutcome(), and validateTarget().

    +

    References densmatr_calcProbOfOutcome(), densmatr_collapseToKnownProbOutcome(), Qureg::isDensityMatrix, qasm_recordMeasurement(), qreal, statevec_calcProbOfOutcome(), statevec_collapseToKnownProbOutcome(), validateMeasurementProb(), validateOutcome(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -194,12 +196,13 @@

    -

    The random outcome generator can be seeded with seedQuESTDefault(), which is safe to use in distributed mode.

    +

    The random outcome generator is seeded by seedQuESTDefault() within createQuESTEnv(), unless later overridden by seedQuEST().

    See also
    Parameters
    @@ -223,22 +226,22 @@

    Definition at line 985 of file QuEST.c.

    -
    985  {
    -
    986  validateTarget(qureg, measureQubit, __func__);
    -
    987 
    -
    988  int outcome;
    -
    989  qreal discardedProb;
    -
    990  if (qureg.isDensityMatrix)
    -
    991  outcome = densmatr_measureWithStats(qureg, measureQubit, &discardedProb);
    -
    992  else
    -
    993  outcome = statevec_measureWithStats(qureg, measureQubit, &discardedProb);
    -
    994 
    -
    995  qasm_recordMeasurement(qureg, measureQubit);
    -
    996  return outcome;
    -
    997 }
    +

    Definition at line 998 of file QuEST.c.

    +
    998  {
    +
    999  validateTarget(qureg, measureQubit, __func__);
    +
    1000 
    +
    1001  int outcome;
    +
    1002  qreal discardedProb;
    +
    1003  if (qureg.isDensityMatrix)
    +
    1004  outcome = densmatr_measureWithStats(qureg, measureQubit, &discardedProb);
    +
    1005  else
    +
    1006  outcome = statevec_measureWithStats(qureg, measureQubit, &discardedProb);
    +
    1007 
    +
    1008  qasm_recordMeasurement(qureg, measureQubit);
    +
    1009  return outcome;
    +
    1010 }
    -

    References densmatr_measureWithStats(), Qureg::isDensityMatrix, qasm_recordMeasurement(), qreal, statevec_measureWithStats(), and validateTarget().

    +

    References densmatr_measureWithStats(), Qureg::isDensityMatrix, qasm_recordMeasurement(), qreal, statevec_measureWithStats(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -279,12 +282,13 @@

    -

    The random outcome generator can be seeded with seedQuESTDefault(), which is safe to use in distributed mode.

    +

    The random outcome generator is seeded by seedQuESTDefault() within createQuESTEnv(), unless later overridden by seedQuEST().

    See also
    Parameters
    @@ -309,39 +313,39 @@

    Definition at line 972 of file QuEST.c.

    -
    972  {
    -
    973  validateTarget(qureg, measureQubit, __func__);
    -
    974 
    -
    975  int outcome;
    -
    976  if (qureg.isDensityMatrix)
    -
    977  outcome = densmatr_measureWithStats(qureg, measureQubit, outcomeProb);
    -
    978  else
    -
    979  outcome = statevec_measureWithStats(qureg, measureQubit, outcomeProb);
    -
    980 
    -
    981  qasm_recordMeasurement(qureg, measureQubit);
    -
    982  return outcome;
    -
    983 }
    +

    Definition at line 985 of file QuEST.c.

    +
    985  {
    +
    986  validateTarget(qureg, measureQubit, __func__);
    +
    987 
    +
    988  int outcome;
    +
    989  if (qureg.isDensityMatrix)
    +
    990  outcome = densmatr_measureWithStats(qureg, measureQubit, outcomeProb);
    +
    991  else
    +
    992  outcome = statevec_measureWithStats(qureg, measureQubit, outcomeProb);
    +
    993 
    +
    994  qasm_recordMeasurement(qureg, measureQubit);
    +
    995  return outcome;
    +
    996 }
    -

    References densmatr_measureWithStats(), Qureg::isDensityMatrix, qasm_recordMeasurement(), statevec_measureWithStats(), and validateTarget().

    +

    References densmatr_measureWithStats(), Qureg::isDensityMatrix, qasm_recordMeasurement(), statevec_measureWithStats(), and validateTarget().

    Referenced by TEST_CASE().

    -
    void validateMeasurementProb(qreal prob, const char *caller)
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void validateOutcome(int outcome, const char *caller)
    -
    qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    +
    void validateMeasurementProb(qreal prob, const char *caller)
    +
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    +
    void validateOutcome(int outcome, const char *caller)
    +
    qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    #define qreal
    -
    void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
    Definition: QuEST_cpu.c:785
    +
    void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
    Definition: QuEST_cpu.c:791
    void qasm_recordMeasurement(Qureg qureg, int measureQubit)
    Definition: QuEST_qasm.c:411
    -
    void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    -
    int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Definition: QuEST_common.c:374
    +
    void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    +
    int statevec_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Definition: QuEST_common.c:364
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    -
    qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    -
    int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Definition: QuEST_common.c:382
    +
    qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    +
    int densmatr_measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Definition: QuEST_common.c:372
    diff --git a/docs/group__operator.html b/docs/group__operator.html index 5ba8a5bac..77c38239c 100644 --- a/docs/group__operator.html +++ b/docs/group__operator.html @@ -27,7 +27,7 @@ @@ -110,6 +110,9 @@

    void applyPhaseFuncOverrides (Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
     Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices. More...
     
    void applyProjector (Qureg qureg, int qubit, int outcome)
     Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection. More...
     
    void applyQFT (Qureg qureg, int *qubits, int numQubits)
     Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg. More...
     
    + + + + + + + + + + + + + + + + + + + + + + + +
    void applyProjector (Qureg qureg,
    int qubit,
    int outcome 
    )
    +
    + +

    Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection.

    +

    This function zeroes all amplitudes in the state-vector or density-matrix which correspond to the opposite outcome given. Unlike collapseToOutcome(), it does not thereafter normalise qureg, and hence may leave it in a non-physical state.

    +

    Note there is no requirement that the outcome state has a non-zero proability, and hence this function may leave qureg in a blank state, like that produced by initBlankState().

    +
    See also
    +
    +
    Parameters
    + + + + +
    [in,out]qurega state-vector or density matrix to modify
    [in]qubitthe qubit to which to apply the projector
    [in]thesingle-qubit outcome (0 or 1) to project qubit into
    +
    +
    +
    Exceptions
    + + +
    invalidQuESTInputError()
      +
    • if qubit is outside [0, qureg.numQubitsRepresented)
    • +
    • if outcome is not in {0,1}
    • +
    +
    +
    +
    +
    Author
    Tyson Jones
    + +

    Definition at line 888 of file QuEST.c.

    +
    888  {
    +
    889  validateTarget(qureg, qubit, __func__);
    +
    890  validateOutcome(outcome, __func__);
    +
    891 
    +
    892  qreal renorm = 1;
    +
    893 
    +
    894  if (qureg.isDensityMatrix)
    +
    895  densmatr_collapseToKnownProbOutcome(qureg, qubit, outcome, renorm);
    +
    896  else
    +
    897  statevec_collapseToKnownProbOutcome(qureg, qubit, outcome, renorm);
    +
    898 
    +
    899  qasm_recordComment(qureg, "Here, qubit %d was un-physically projected into outcome %d", qubit, outcome);
    +
    900 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordPhaseFunc(), shiftIndices(), statevec_applyPhaseFuncOverrides(), validateBitEncoding(), validateMultiQubits(), validatePhaseFuncOverrides(), and validatePhaseFuncTerms().

    +

    References densmatr_collapseToKnownProbOutcome(), Qureg::isDensityMatrix, qasm_recordComment(), qreal, statevec_collapseToKnownProbOutcome(), validateOutcome(), and validateTarget().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -2304,7 +2390,7 @@

    be the $j\text{th}$ such state.
  • let $n =$ numQubits, and $N =$ qureg.numQubitsRepresented.
    Then, this function effects

    -\[ (\text{QFT}\otimes 1) \, \left( \sum\limits_{j=0}^{2^N-1} \alpha_j \, |x_j,r_j\rangle \right) = \frac{1}{\sqrt{2^n}} \sum\limits_{j=0}^{2^N-1} \alpha_j \left( \sum\limits_{y=0}^{2^n-1} e^{2 \pi \, i \, x_j \, y / 2^N} \; |y,r_j \rangle \right) \] +\[ (\text{QFT}\otimes 1) \, \left( \sum\limits_{j=0}^{2^N-1} \alpha_j \, |x_j,r_j\rangle \right) = \frac{1}{\sqrt{2^n}} \sum\limits_{j=0}^{2^N-1} \alpha_j \left( \sum\limits_{y=0}^{2^n-1} e^{2 \pi \, i \, x_j \, y / 2^n} \; |y,r_j \rangle \right) \]

  • @@ -2350,20 +2436,20 @@

    Author
    Tyson Jones

    -

    Definition at line 867 of file QuEST.c.

    -
    867  {
    -
    868  validateMultiTargets(qureg, qubits, numQubits, __func__);
    -
    869 
    -
    870  qasm_recordComment(qureg, "Beginning of QFT circuit");
    -
    871 
    -
    872  agnostic_applyQFT(qureg, qubits, numQubits);
    -
    873 
    -
    874  qasm_recordComment(qureg, "End of QFT circuit");
    -
    875 }
    +

    Definition at line 866 of file QuEST.c.

    +
    866  {
    +
    867  validateMultiTargets(qureg, qubits, numQubits, __func__);
    +
    868 
    +
    869  qasm_recordComment(qureg, "Beginning of QFT circuit");
    +
    870 
    +
    871  agnostic_applyQFT(qureg, qubits, numQubits);
    +
    872 
    +
    873  qasm_recordComment(qureg, "End of QFT circuit");
    +
    874 }
    -

    References agnostic_applyQFT(), qasm_recordComment(), and validateMultiTargets().

    +

    References agnostic_applyQFT(), qasm_recordComment(), and validateMultiTargets().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -2467,103 +2553,106 @@

    Author
    Tyson Jones
    -

    Definition at line 1057 of file QuEST.c.

    -
    1057  {
    -
    1058  validateTrotterParams(order, reps, __func__);
    -
    1059  validatePauliHamil(hamil, __func__);
    -
    1060  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
    -
    1061 
    -
    1062  qasm_recordComment(qureg,
    -
    1063  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
    -
    1064  time, order, reps);
    -
    1065 
    -
    1066  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
    -
    1067 
    -
    1068  qasm_recordComment(qureg, "End of Trotter circuit");
    -
    1069 }
    +

    Definition at line 1070 of file QuEST.c.

    +
    1070  {
    +
    1071  validateTrotterParams(order, reps, __func__);
    +
    1072  validatePauliHamil(hamil, __func__);
    +
    1073  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
    +
    1074 
    +
    1075  qasm_recordComment(qureg,
    +
    1076  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
    +
    1077  time, order, reps);
    +
    1078 
    +
    1079  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
    +
    1080 
    +
    1081  qasm_recordComment(qureg, "End of Trotter circuit");
    +
    1082 }
    -

    References agnostic_applyTrotterCircuit(), qasm_recordComment(), validateMatchingQuregPauliHamilDims(), validatePauliHamil(), and validateTrotterParams().

    +

    References agnostic_applyTrotterCircuit(), qasm_recordComment(), validateMatchingQuregPauliHamilDims(), validatePauliHamil(), and validateTrotterParams().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    -
    void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:727
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:814
    -
    void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
    Definition: QuEST_common.c:836
    -
    void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
    -
    void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
    -
    void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
    +
    void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:726
    +
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    +
    void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:813
    +
    void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
    Definition: QuEST_common.c:849
    +
    void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
    +
    void validateOutcome(int outcome, const char *caller)
    +
    void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
    +
    void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
    @ PAULI_Z
    Definition: QuEST.h:96
    void shiftIndices(int *indices, int numIndices, int shift)
    Definition: QuEST_common.c:156
    -
    void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:797
    +
    void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:796
    @ PAULI_I
    Definition: QuEST.h:96
    -
    void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
    -
    void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:571
    -
    void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    -
    void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    +
    void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
    +
    void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:561
    +
    void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    +
    void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    @ NORM
    Definition: QuEST.h:232
    -
    void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
    -
    void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
    +
    void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
    +
    void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
    @ UNSIGNED
    Definition: QuEST.h:269
    -
    void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:744
    +
    void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:743
    @ INVERSE_DISTANCE
    Definition: QuEST.h:234
    -
    void validateNumPauliSumTerms(int numTerms, const char *caller)
    +
    void validateNumPauliSumTerms(int numTerms, const char *caller)
    #define qreal
    @ PAULI_X
    Definition: QuEST.h:96
    -
    void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
    -
    void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
    -
    void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
    Definition: QuEST_cpu.c:4406
    +
    void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
    +
    void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
    Definition: QuEST_cpu.c:791
    +
    void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
    +
    void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
    Definition: QuEST_cpu.c:4446
    phaseFunc
    Flags for specifying named phase functions.
    Definition: QuEST.h:231
    qreal * termCoeffs
    The real coefficient of each Pauli product. This is an array of length PauliHamil....
    Definition: QuEST.h:283
    -
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:1080
    -
    void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Definition: QuEST_common.c:827
    -
    void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
    Definition: QuEST_cpu.c:4228
    +
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:1093
    +
    void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Definition: QuEST_common.c:840
    +
    void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
    Definition: QuEST_cpu.c:4268
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    -
    void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Definition: QuEST_cpu.c:4007
    +
    void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Definition: QuEST_cpu.c:4047
    @ SCALED_PRODUCT
    Definition: QuEST.h:233
    -
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    +
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    +
    void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:285
    long long int getQubitBitMask(int *qubits, int numQubits)
    Definition: QuEST_common.c:50
    @ PAULI_Y
    Definition: QuEST.h:96
    -
    void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
    Definition: QuEST.c:849
    +
    void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
    Definition: QuEST.c:848
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:121
    @ SCALED_INVERSE_SHIFTED_NORM
    Definition: QuEST.h:232
    -
    void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:583
    -
    void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
    +
    void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:573
    +
    void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
    void startRecordingQASM(Qureg qureg)
    Enable QASM recording.
    Definition: QuEST.c:87
    -
    void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Definition: QuEST_common.c:548
    -
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:1035
    -
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:1090
    -
    void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:762
    +
    void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Definition: QuEST_common.c:538
    +
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:1048
    +
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:1103
    +
    void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:761
    +
    void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
    void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
    Definition: QuEST_common.c:161
    -
    void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
    -
    void validatePauliHamil(PauliHamil hamil, const char *caller)
    -
    void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:779
    -
    void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
    +
    void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
    +
    void validatePauliHamil(PauliHamil hamil, const char *caller)
    +
    void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:778
    +
    void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    -
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    +
    void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:327
    -
    void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
    -
    void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
    -
    void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
    +
    void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
    +
    void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
    +
    void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
    void qasm_recordMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Definition: QuEST_qasm.c:666
    -
    void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
    Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
    Definition: QuEST.c:832
    +
    void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
    Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
    Definition: QuEST.c:831
    @ SCALED_INVERSE_SHIFTED_DISTANCE
    Definition: QuEST.h:234
    -
    void validateTrotterParams(int order, int reps, const char *caller)
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    +
    void validateTrotterParams(int order, int reps, const char *caller)
    +
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    #define M_PI
    Definition: QuEST_common.c:41
    -
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1057
    +
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1070
    void qasm_recordNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc funcName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Definition: QuEST_qasm.c:726
    bitEncoding
    Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
    Definition: QuEST.h:269
    void printRecordedQASM(Qureg qureg)
    Print recorded QASM to stdout.
    Definition: QuEST.c:99
    void qasm_recordPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Definition: QuEST_qasm.c:490
    -
    void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
    Definition: QuEST_cpu.c:4305
    +
    void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
    Definition: QuEST_cpu.c:4345
    @ SCALED_INVERSE_NORM
    Definition: QuEST.h:232
    -
    void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
    +
    void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
    diff --git a/docs/group__qasm.html b/docs/group__qasm.html index 081b54155..d9e4e0c31 100644 --- a/docs/group__qasm.html +++ b/docs/group__qasm.html @@ -27,7 +27,7 @@ @@ -273,7 +273,7 @@

    105  validateFileOpened(success, filename, __func__);
    106 }
    -

    References qasm_writeRecordedToFile(), and validateFileOpened().

    +

    References qasm_writeRecordedToFile(), and validateFileOpened().

    @@ -281,7 +281,7 @@

    void qasm_printRecorded(Qureg qureg)
    Definition: QuEST_qasm.c:871
    void qasm_clearRecorded(Qureg qureg)
    Definition: QuEST_qasm.c:864
    void qasm_startRecording(Qureg qureg)
    Definition: QuEST_qasm.c:85
    -
    void validateFileOpened(int opened, char *fn, const char *caller)
    +
    void validateFileOpened(int opened, char *fn, const char *caller)
    void qasm_stopRecording(Qureg qureg)
    Definition: QuEST_qasm.c:89
    int qasm_writeRecordedToFile(Qureg qureg, char *filename)
    returns success of file write
    Definition: QuEST_qasm.c:876
    diff --git a/docs/group__testutilities.html b/docs/group__testutilities.html index 9bac3eb64..f0bc107b5 100644 --- a/docs/group__testutilities.html +++ b/docs/group__testutilities.html @@ -27,7 +27,7 @@ @@ -1694,7 +1694,7 @@

    981  return allAmpsAgree;
    982 }
    -

    References Qureg::chunkId, copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References Qureg::chunkId, copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    @@ -1818,7 +1818,7 @@

    922  return allAmpsAgree;
    923 }
    -

    References Qureg::chunkId, copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References Qureg::chunkId, copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    @@ -1924,7 +1924,7 @@

    877  return allAmpsAgree;
    878 }
    -

    References copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    @@ -2125,15 +2125,15 @@

    Author
    Tyson Jones

    Returns log2 of numbers which must be gauranteed to be 2^n.

    -

    Definition at line 324 of file QuEST_validation.c.

    -
    324  {
    -
    325  unsigned int l = 0;
    -
    326  while (num >>= 1)
    -
    327  l++;
    -
    328  return l;
    -
    329 }
    +

    Definition at line 328 of file QuEST_validation.c.

    +
    328  {
    +
    329  unsigned int l = 0;
    +
    330  while (num >>= 1)
    +
    331  l++;
    +
    332  return l;
    +
    333 }
    -

    Referenced by applyReferenceMatrix(), applyReferenceOp(), TEST_CASE(), validateDiagPauliHamilFromFile(), validateNumQubitsInDiagOp(), and validateNumQubitsInQureg().

    +

    Referenced by applyReferenceMatrix(), applyReferenceOp(), TEST_CASE(), validateDiagPauliHamilFromFile(), validateNumQubitsInDiagOp(), and validateNumQubitsInQureg().

    @@ -2171,7 +2171,7 @@

    1385  syncQuESTEnv(QUEST_ENV);
    1386 }
    -

    References QUEST_ENV, QuESTEnv::rank, and syncQuESTEnv().

    +

    References QUEST_ENV, QuESTEnv::rank, and syncQuESTEnv().

    Referenced by TEST_CASE().

    @@ -4755,7 +4755,7 @@

    1110  return matr;
    1111 }
    -

    References copyStateFromGPU(), DEMAND, getZeroMatrix(), Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References copyStateFromGPU(), DEMAND, getZeroMatrix(), Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    @@ -4805,7 +4805,7 @@

    1226  copyStateToGPU(qureg);
    1227 }
    -

    References Qureg::chunkId, copyStateToGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References Qureg::chunkId, copyStateToGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numQubitsRepresented, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    @@ -4854,7 +4854,7 @@

    1212  copyStateToGPU(qureg);
    1213 }
    -

    References Qureg::chunkId, copyStateToGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References Qureg::chunkId, copyStateToGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    Referenced by TEST_CASE().

    @@ -4986,7 +4986,7 @@

    1152  return vec;
    1153 }
    -

    References copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qcomp, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    +

    References copyStateFromGPU(), DEMAND, Qureg::isDensityMatrix, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, qcomp, qreal, QUEST_ENV, Qureg::stateVec, and syncQuESTEnv().

    Referenced by TEST_CASE(), and toQMatrix().

    @@ -5036,7 +5036,7 @@

    1372  syncQuESTEnv(QUEST_ENV);
    1373 }
    -

    References QUEST_ENV, QuESTEnv::rank, and syncQuESTEnv().

    +

    References QUEST_ENV, QuESTEnv::rank, and syncQuESTEnv().

    Referenced by TEST_CASE().

    @@ -5046,13 +5046,13 @@

    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:304
    long long int getUnsigned(long long int twosComp, int numBits)
    Return the unsigned value of a number, made of #numBits bits, which under two's complement,...
    Definition: utilities.cpp:1298
    -
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:39
    +
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:45
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    -
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    +
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    @ PAULI_Z
    Definition: QuEST.h:96
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    -
    int rank
    Definition: QuEST.h:363
    +
    int rank
    Definition: QuEST.h:364
    #define macro_copyComplexMatrix(dest, src)
    Copies ComplexMatrix structures into a QMatrix.
    Definition: utilities.cpp:1039
    @ PAULI_I
    Definition: QuEST.h:96
    QMatrix getConjugateTranspose(QMatrix a)
    Returns the conjugate transpose of the complex square matrix a.
    Definition: utilities.cpp:189
    @@ -5080,7 +5080,7 @@

    qreal * termCoeffs
    The real coefficient of each Pauli product. This is an array of length PauliHamil....
    Definition: QuEST.h:283
    #define qcomp
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    +
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:42
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:300
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:285
    @ PAULI_Y
    Definition: QuEST.h:96
    diff --git a/docs/group__type.html b/docs/group__type.html index 5ec006a7b..c9cdcea7c 100644 --- a/docs/group__type.html +++ b/docs/group__type.html @@ -27,7 +27,7 @@ @@ -296,7 +296,7 @@

    Author
    Tyson Jones
    -

    Definition at line 5456 of file QuEST.h.

    +

    Definition at line 5521 of file QuEST.h.

    @@ -584,7 +584,7 @@

    74  return newQureg;
    75 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, qasm_setup(), statevec_cloneQureg(), and statevec_createQureg().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, qasm_setup(), statevec_cloneQureg(), and statevec_createQureg().

    Referenced by TEST_CASE().

    @@ -655,31 +655,31 @@

    Author
    Tyson Jones
    -

    Definition at line 1335 of file QuEST.c.

    -
    1335  {
    -
    1336  validateNumQubitsInMatrix(numQubits, __func__);
    -
    1337 
    -
    1338  int numRows = 1 << numQubits;
    -
    1339 
    -
    1340  ComplexMatrixN m = {
    -
    1341  .numQubits = numQubits,
    -
    1342  .real = malloc(numRows * sizeof *m.real),
    -
    1343  .imag = malloc(numRows * sizeof *m.imag)};
    -
    1344 
    -
    1345  for (int n=0; n < 1<<numQubits; n++) {
    -
    1346  m.real[n] = calloc(numRows, sizeof **m.real);
    -
    1347  m.imag[n] = calloc(numRows, sizeof **m.imag);
    -
    1348  }
    -
    1349 
    -
    1350  // error if the ComplexMatrixN was not successfully malloc'ds
    -
    1351  validateMatrixInit(m, __func__);
    -
    1352 
    -
    1353  return m;
    -
    1354  }
    +

    Definition at line 1348 of file QuEST.c.

    +
    1348  {
    +
    1349  validateNumQubitsInMatrix(numQubits, __func__);
    +
    1350 
    +
    1351  int numRows = 1 << numQubits;
    +
    1352 
    +
    1353  ComplexMatrixN m = {
    +
    1354  .numQubits = numQubits,
    +
    1355  .real = malloc(numRows * sizeof *m.real),
    +
    1356  .imag = malloc(numRows * sizeof *m.imag)};
    +
    1357 
    +
    1358  for (int n=0; n < 1<<numQubits; n++) {
    +
    1359  m.real[n] = calloc(numRows, sizeof **m.real);
    +
    1360  m.imag[n] = calloc(numRows, sizeof **m.imag);
    +
    1361  }
    +
    1362 
    +
    1363  // error if the ComplexMatrixN was not successfully malloc'ds
    +
    1364  validateMatrixInit(m, __func__);
    +
    1365 
    +
    1366  return m;
    +
    1367  }
    -

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, validateMatrixInit(), and validateNumQubitsInMatrix().

    +

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, validateMatrixInit(), and validateNumQubitsInMatrix().

    -

    Referenced by densmatr_mixMultiQubitKrausMap(), and TEST_CASE().

    +

    Referenced by densmatr_mixMultiQubitKrausMap(), densmatr_mixTwoQubitKrausMap(), and TEST_CASE().

    @@ -816,7 +816,7 @@

    61  return qureg;
    62 }
    -

    References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

    +

    References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

    Referenced by TEST_CASE().

    @@ -911,14 +911,14 @@

    Author
    Tyson Jones
    -

    Definition at line 1503 of file QuEST.c.

    -
    1503  {
    -
    1504  validateNumQubitsInDiagOp(numQubits, env.numRanks, __func__);
    -
    1505 
    -
    1506  return agnostic_createDiagonalOp(numQubits, env);
    -
    1507 }
    +

    Definition at line 1518 of file QuEST.c.

    +
    1518  {
    +
    1519  validateNumQubitsInDiagOp(numQubits, env.numRanks, __func__);
    +
    1520 
    +
    1521  return agnostic_createDiagonalOp(numQubits, env);
    +
    1522 }
    -

    References agnostic_createDiagonalOp(), QuESTEnv::numRanks, and validateNumQubitsInDiagOp().

    +

    References agnostic_createDiagonalOp(), QuESTEnv::numRanks, and validateNumQubitsInDiagOp().

    Referenced by TEST_CASE().

    @@ -998,19 +998,19 @@

    Definition at line 1543 of file QuEST.c.

    -
    1543  {
    -
    1544  PauliHamil h = createPauliHamilFromFile(fn); // validates fn
    -
    1545  validateDiagPauliHamilFromFile(h, env.numRanks, __func__); // destroys h if invalid
    -
    1546 
    - - -
    1549 
    -
    1550  destroyPauliHamil(h);
    -
    1551  return op;
    -
    1552 }
    +

    Definition at line 1558 of file QuEST.c.

    +
    1558  {
    +
    1559  PauliHamil h = createPauliHamilFromFile(fn); // validates fn
    +
    1560  validateDiagPauliHamilFromFile(h, env.numRanks, __func__); // destroys h if invalid
    +
    1561 
    + + +
    1564 
    +
    1565  destroyPauliHamil(h);
    +
    1566  return op;
    +
    1567 }
    -

    References agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), createPauliHamilFromFile(), destroyPauliHamil(), PauliHamil::numQubits, QuESTEnv::numRanks, and validateDiagPauliHamilFromFile().

    +

    References agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), createPauliHamilFromFile(), destroyPauliHamil(), PauliHamil::numQubits, QuESTEnv::numRanks, and validateDiagPauliHamilFromFile().

    Referenced by TEST_CASE().

    @@ -1080,26 +1080,26 @@

    Author
    Tyson Jones
    -

    Definition at line 1383 of file QuEST.c.

    -
    1383  {
    -
    1384  validateHamilParams(numQubits, numSumTerms, __func__);
    -
    1385 
    -
    1386  PauliHamil h;
    -
    1387  h.numQubits = numQubits;
    -
    1388  h.numSumTerms = numSumTerms;
    -
    1389  h.termCoeffs = malloc(numSumTerms * sizeof *h.termCoeffs);
    -
    1390  h.pauliCodes = malloc(numQubits*numSumTerms * sizeof *h.pauliCodes);
    -
    1391 
    -
    1392  // initialise pauli codes to identity
    -
    1393  for (int i=0; i<numQubits*numSumTerms; i++)
    -
    1394  h.pauliCodes[i] = PAULI_I;
    -
    1395 
    -
    1396  return h;
    -
    1397 }
    +

    Definition at line 1398 of file QuEST.c.

    +
    1398  {
    +
    1399  validateHamilParams(numQubits, numSumTerms, __func__);
    +
    1400 
    +
    1401  PauliHamil h;
    +
    1402  h.numQubits = numQubits;
    +
    1403  h.numSumTerms = numSumTerms;
    +
    1404  h.termCoeffs = malloc(numSumTerms * sizeof *h.termCoeffs);
    +
    1405  h.pauliCodes = malloc(numQubits*numSumTerms * sizeof *h.pauliCodes);
    +
    1406 
    +
    1407  // initialise pauli codes to identity
    +
    1408  for (int i=0; i<numQubits*numSumTerms; i++)
    +
    1409  h.pauliCodes[i] = PAULI_I;
    +
    1410 
    +
    1411  return h;
    +
    1412 }
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and validateHamilParams().

    +

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PauliHamil::pauliCodes, PauliHamil::termCoeffs, and validateHamilParams().

    -

    Referenced by createPauliHamilFromFile(), and TEST_CASE().

    +

    Referenced by createPauliHamilFromFile(), and TEST_CASE().

    @@ -1159,94 +1159,94 @@

    Author
    Tyson Jones
    -

    Definition at line 1405 of file QuEST.c.

    -
    1405  {
    -
    1406 
    -
    1407  /* The validation in this function must close the file handle and free
    -
    1408  * allocated memory before raising an error (whether that's a C exit, or
    -
    1409  * an overriden C++ exception).
    -
    1410  */
    -
    1411 
    -
    1412  FILE* file = fopen(fn, "r");
    -
    1413  int success = (file != NULL);
    -
    1414  validateFileOpened(success, fn, __func__);
    -
    1415 
    -
    1416  /* file format: coeff {term} \n where {term} is #numQubits values of
    -
    1417  * 0 1 2 3 signifying I X Y Z acting on that qubit index
    -
    1418  */
    -
    1419 
    -
    1420  // count the number of qubits (ignore trailing whitespace)
    -
    1421  int numQubits = -1; // to exclude coeff at start
    -
    1422  char ch = getc(file);
    -
    1423  char prev = '0'; // anything not space
    -
    1424  while (ch != '\n' && ch != EOF) {
    -
    1425  if (ch == ' ' && prev != ' ') // skip multiple spaces
    -
    1426  numQubits++;
    -
    1427  prev = ch;
    -
    1428  ch = getc(file);
    -
    1429  }
    -
    1430  // edge-case: if we hit EOF/newline without a space
    -
    1431  if (prev != ' ')
    -
    1432  numQubits++;
    -
    1433 
    -
    1434  /* TODO:
    -
    1435  * The below code may break on Windows where newlines are multiple characters
    -
    1436  */
    -
    1437 
    -
    1438  // count the number of terms (being cautious of trailing newlines)
    -
    1439  int numTerms = 0;
    -
    1440  prev = '\n';
    -
    1441  rewind(file);
    -
    1442  while ((ch=getc(file)) != EOF) {
    -
    1443  if (ch == '\n' && prev != '\n')
    -
    1444  numTerms++;
    -
    1445  prev = ch;
    -
    1446  }
    -
    1447  // edge-case: if we hit EOF without a newline, count that line
    -
    1448  if (prev != '\n')
    -
    1449  numTerms++;
    -
    1450 
    -
    1451  // validate the inferred number of terms and qubits (closes file if error)
    -
    1452  validateHamilFileParams(numQubits, numTerms, file, fn, __func__);
    -
    1453 
    -
    1454  // allocate space for PauliHamil data
    -
    1455  PauliHamil h = createPauliHamil(numQubits, numTerms);
    -
    1456 
    -
    1457  // specifier for a qreal number then a space
    -
    1458  char strSpec[50];
    -
    1459  strcpy(strSpec, REAL_SPECIFIER);
    -
    1460  strcat(strSpec, " ");
    -
    1461 
    -
    1462  // collect coefficients and terms
    -
    1463  rewind(file);
    -
    1464  for (int t=0; t<numTerms; t++) {
    -
    1465 
    -
    1466  // record coefficient, and validate (closes file and frees h if error)
    -
    1467  success = fscanf(file, strSpec, &(h.termCoeffs[t])) == 1;
    -
    1468  validateHamilFileCoeffParsed(success, h, file, fn, __func__);
    -
    1469 
    -
    1470  // record Pauli operations, and validate (closes file and frees h if error)
    -
    1471  for (int q=0; q<numQubits; q++) {
    -
    1472  int i = t*numQubits + q;
    -
    1473 
    -
    1474  // verbose, to avoid type warnings
    -
    1475  int code;
    -
    1476  success = fscanf(file, "%d ", &code) == 1;
    -
    1477  h.pauliCodes[i] = (enum pauliOpType) code;
    -
    1478  validateHamilFilePauliParsed(success, h, file, fn, __func__);
    -
    1479  validateHamilFilePauliCode(h.pauliCodes[i], h, file, fn, __func__);
    -
    1480  }
    -
    1481 
    -
    1482  // the trailing newline is magically eaten
    -
    1483  }
    +

    Definition at line 1420 of file QuEST.c.

    +
    1420  {
    +
    1421 
    +
    1422  /* The validation in this function must close the file handle and free
    +
    1423  * allocated memory before raising an error (whether that's a C exit, or
    +
    1424  * an overriden C++ exception).
    +
    1425  */
    +
    1426 
    +
    1427  FILE* file = fopen(fn, "r");
    +
    1428  int success = (file != NULL);
    +
    1429  validateFileOpened(success, fn, __func__);
    +
    1430 
    +
    1431  /* file format: coeff {term} \n where {term} is #numQubits values of
    +
    1432  * 0 1 2 3 signifying I X Y Z acting on that qubit index
    +
    1433  */
    +
    1434 
    +
    1435  // count the number of qubits (ignore trailing whitespace)
    +
    1436  int numQubits = -1; // to exclude coeff at start
    +
    1437  char ch = getc(file);
    +
    1438  char prev = '0'; // anything not space
    +
    1439  while (ch != '\n' && ch != EOF) {
    +
    1440  if (ch == ' ' && prev != ' ') // skip multiple spaces
    +
    1441  numQubits++;
    +
    1442  prev = ch;
    +
    1443  ch = getc(file);
    +
    1444  }
    +
    1445  // edge-case: if we hit EOF/newline without a space
    +
    1446  if (prev != ' ')
    +
    1447  numQubits++;
    +
    1448 
    +
    1449  /* TODO:
    +
    1450  * The below code may break on Windows where newlines are multiple characters
    +
    1451  */
    +
    1452 
    +
    1453  // count the number of terms (being cautious of trailing newlines)
    +
    1454  int numTerms = 0;
    +
    1455  prev = '\n';
    +
    1456  rewind(file);
    +
    1457  while ((ch=getc(file)) != EOF) {
    +
    1458  if (ch == '\n' && prev != '\n')
    +
    1459  numTerms++;
    +
    1460  prev = ch;
    +
    1461  }
    +
    1462  // edge-case: if we hit EOF without a newline, count that line
    +
    1463  if (prev != '\n')
    +
    1464  numTerms++;
    +
    1465 
    +
    1466  // validate the inferred number of terms and qubits (closes file if error)
    +
    1467  validateHamilFileParams(numQubits, numTerms, file, fn, __func__);
    +
    1468 
    +
    1469  // allocate space for PauliHamil data
    +
    1470  PauliHamil h = createPauliHamil(numQubits, numTerms);
    +
    1471 
    +
    1472  // specifier for a qreal number then a space
    +
    1473  char strSpec[50];
    +
    1474  strcpy(strSpec, REAL_SPECIFIER);
    +
    1475  strcat(strSpec, " ");
    +
    1476 
    +
    1477  // collect coefficients and terms
    +
    1478  rewind(file);
    +
    1479  for (int t=0; t<numTerms; t++) {
    +
    1480 
    +
    1481  // record coefficient, and validate (closes file and frees h if error)
    +
    1482  success = fscanf(file, strSpec, &(h.termCoeffs[t])) == 1;
    +
    1483  validateHamilFileCoeffParsed(success, h, file, fn, __func__);
    1484 
    -
    1485  fclose(file);
    -
    1486  return h;
    -
    1487 }
    +
    1485  // record Pauli operations, and validate (closes file and frees h if error)
    +
    1486  for (int q=0; q<numQubits; q++) {
    +
    1487  int i = t*numQubits + q;
    +
    1488 
    +
    1489  // verbose, to avoid type warnings
    +
    1490  int code;
    +
    1491  success = fscanf(file, "%d ", &code) == 1;
    +
    1492  h.pauliCodes[i] = (enum pauliOpType) code;
    +
    1493  validateHamilFilePauliParsed(success, h, file, fn, __func__);
    +
    1494  validateHamilFilePauliCode(h.pauliCodes[i], h, file, fn, __func__);
    +
    1495  }
    +
    1496 
    +
    1497  // the trailing newline is magically eaten
    +
    1498  }
    +
    1499 
    +
    1500  fclose(file);
    +
    1501  return h;
    +
    1502 }
    -

    References createPauliHamil(), PauliHamil::pauliCodes, PauliHamil::termCoeffs, validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    +

    References createPauliHamil(), PauliHamil::pauliCodes, PauliHamil::termCoeffs, validateFileOpened(), validateHamilFileCoeffParsed(), validateHamilFileParams(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    -

    Referenced by createDiagonalOpFromPauliHamilFile(), and TEST_CASE().

    +

    Referenced by createDiagonalOpFromPauliHamilFile(), and TEST_CASE().

    @@ -1306,12 +1306,14 @@

    154 
    155  validateNumRanks(env.numRanks, __func__);
    156 
    - -
    158 
    -
    159  return env;
    -
    160 }
    +
    157  env.seeds = NULL;
    +
    158  env.numSeeds = 0;
    +
    159  seedQuESTDefault(&env);
    +
    160 
    +
    161  return env;
    +
    162 }
    -

    References GPUExists(), QuESTEnv::numRanks, QuESTEnv::rank, seedQuESTDefault(), and validateNumRanks().

    +

    References GPUExists(), QuESTEnv::numRanks, QuESTEnv::numSeeds, QuESTEnv::rank, seedQuESTDefault(), QuESTEnv::seeds, and validateNumRanks().

    Referenced by main().

    @@ -1495,7 +1497,7 @@

    47  return qureg;
    48 }
    -

    References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

    +

    References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

    Referenced by TEST_CASE().

    @@ -1545,26 +1547,26 @@

    Author
    Tyson Jones
    -

    Definition at line 1356 of file QuEST.c.

    -
    1356  {
    -
    1357  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
    -
    1358  * in createComplexMatrixN fail, which already prompts an error. Hence
    -
    1359  * this check if useless
    -
    1360  */
    -
    1361  validateMatrixInit(m, __func__);
    -
    1362 
    -
    1363  int numRows = 1 << m.numQubits;
    -
    1364  for (int r=0; r < numRows; r++) {
    -
    1365  free(m.real[r]);
    -
    1366  free(m.imag[r]);
    -
    1367  }
    -
    1368  free(m.real);
    -
    1369  free(m.imag);
    -
    1370 }
    +

    Definition at line 1369 of file QuEST.c.

    +
    1369  {
    +
    1370  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
    +
    1371  * in createComplexMatrixN fail, which already prompts an error. Hence
    +
    1372  * this check if useless
    +
    1373  */
    +
    1374  validateMatrixInit(m, __func__);
    +
    1375 
    +
    1376  int numRows = 1 << m.numQubits;
    +
    1377  for (int r=0; r < numRows; r++) {
    +
    1378  free(m.real[r]);
    +
    1379  free(m.imag[r]);
    +
    1380  }
    +
    1381  free(m.real);
    +
    1382  free(m.imag);
    +
    1383 }
    -

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

    +

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

    -

    Referenced by densmatr_mixMultiQubitKrausMap(), and TEST_CASE().

    +

    Referenced by densmatr_mixMultiQubitKrausMap(), densmatr_mixTwoQubitKrausMap(), and TEST_CASE().

    @@ -1617,15 +1619,15 @@

    Author
    Tyson Jones
    -

    Definition at line 1509 of file QuEST.c.

    -
    1509  {
    -
    1510  // env accepted for API consistency
    -
    1511  validateDiagOpInit(op, __func__);
    -
    1512 
    - -
    1514 }
    +

    Definition at line 1524 of file QuEST.c.

    +
    1524  {
    +
    1525  // env accepted for API consistency
    +
    1526  validateDiagOpInit(op, __func__);
    +
    1527 
    + +
    1529 }
    -

    References agnostic_destroyDiagonalOp(), and validateDiagOpInit().

    +

    References agnostic_destroyDiagonalOp(), and validateDiagOpInit().

    Referenced by TEST_CASE().

    @@ -1656,16 +1658,16 @@

    Author
    Tyson Jones
    -

    Definition at line 1399 of file QuEST.c.

    -
    1399  {
    -
    1400 
    -
    1401  free(h.termCoeffs);
    -
    1402  free(h.pauliCodes);
    -
    1403 }
    +

    Definition at line 1414 of file QuEST.c.

    +
    1414  {
    +
    1415 
    +
    1416  free(h.termCoeffs);
    +
    1417  free(h.pauliCodes);
    +
    1418 }

    References PauliHamil::pauliCodes, and PauliHamil::termCoeffs.

    -

    Referenced by createDiagonalOpFromPauliHamilFile(), TEST_CASE(), validateDiagPauliHamilFromFile(), validateHamilFileCoeffParsed(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    +

    Referenced by createDiagonalOpFromPauliHamilFile(), TEST_CASE(), validateDiagPauliHamilFromFile(), validateHamilFileCoeffParsed(), validateHamilFilePauliCode(), and validateHamilFilePauliParsed().

    @@ -1699,14 +1701,18 @@

    Author
    Ania Brown
    -

    Definition at line 172 of file QuEST_cpu_distributed.c.

    -
    172  {
    -
    173  int finalized;
    -
    174  MPI_Finalized(&finalized);
    -
    175  if (!finalized) MPI_Finalize();
    -
    176  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
    -
    177 }
    +

    Definition at line 174 of file QuEST_cpu_distributed.c.

    +
    174  {
    +
    175  free(env.seeds);
    +
    176 
    +
    177  int finalized;
    +
    178  MPI_Finalized(&finalized);
    +
    179  if (!finalized) MPI_Finalize();
    +
    180  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
    +
    181 }
    +

    References QuESTEnv::seeds.

    +

    Referenced by main().

    @@ -1763,7 +1769,7 @@

    79  qasm_free(qureg);
    80 }
    -

    References qasm_free(), and statevec_destroyQureg().

    +

    References qasm_free(), and statevec_destroyQureg().

    Referenced by TEST_CASE().

    @@ -1827,19 +1833,19 @@

    Author
    Tyson Jones
    -

    Definition at line 1372 of file QuEST.c.

    -
    1372  {
    -
    1373  validateMatrixInit(m, __func__);
    -
    1374 
    -
    1375  int dim = 1 << m.numQubits;
    -
    1376  for (int i=0; i<dim; i++)
    -
    1377  for (int j=0; j<dim; j++) {
    -
    1378  m.real[i][j] = re[i][j];
    -
    1379  m.imag[i][j] = im[i][j];
    -
    1380  }
    -
    1381 }
    +

    Definition at line 1386 of file QuEST.c.

    +
    1386  {
    +
    1387  validateMatrixInit(m, __func__);
    +
    1388 
    +
    1389  int dim = 1 << m.numQubits;
    +
    1390  for (int i=0; i<dim; i++)
    +
    1391  for (int j=0; j<dim; j++) {
    +
    1392  m.real[i][j] = re[i][j];
    +
    1393  m.imag[i][j] = im[i][j];
    +
    1394  }
    +
    1395 }
    -

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

    +

    References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

    @@ -1907,14 +1913,14 @@

    Author
    Tyson Jones
    -

    Definition at line 1522 of file QuEST.c.

    -
    1522  {
    -
    1523  validateDiagOpInit(op, __func__);
    -
    1524 
    -
    1525  agnostic_setDiagonalOpElems(op, 0, real, imag, 1LL << op.numQubits);
    -
    1526 }
    +

    Definition at line 1537 of file QuEST.c.

    +
    1537  {
    +
    1538  validateDiagOpInit(op, __func__);
    +
    1539 
    +
    1540  agnostic_setDiagonalOpElems(op, 0, real, imag, 1LL << op.numQubits);
    +
    1541 }
    -

    References agnostic_setDiagonalOpElems(), DiagonalOp::numQubits, and validateDiagOpInit().

    +

    References agnostic_setDiagonalOpElems(), DiagonalOp::numQubits, and validateDiagOpInit().

    Referenced by TEST_CASE().

    @@ -1995,16 +2001,16 @@

    Definition at line 1535 of file QuEST.c.

    -
    1535  {
    -
    1536  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
    -
    1537  validateDiagOpInit(op, __func__);
    -
    1538  validateDiagPauliHamil(op, hamil, __func__);
    -
    1539 
    - -
    1541 }
    +

    Definition at line 1550 of file QuEST.c.

    +
    1550  {
    +
    1551  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
    +
    1552  validateDiagOpInit(op, __func__);
    +
    1553  validateDiagPauliHamil(op, hamil, __func__);
    +
    1554 
    + +
    1556 }
    -

    References agnostic_initDiagonalOpFromPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, validateDiagOpInit(), validateDiagPauliHamil(), and validateHamilParams().

    +

    References agnostic_initDiagonalOpFromPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, validateDiagOpInit(), validateDiagPauliHamil(), and validateHamilParams().

    Referenced by TEST_CASE().

    @@ -2083,22 +2089,22 @@

    Author
    Tyson Jones
    -

    Definition at line 1489 of file QuEST.c.

    -
    1489  {
    -
    1490  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
    -
    1491  validatePauliCodes(codes, hamil.numSumTerms*hamil.numQubits, __func__);
    -
    1492 
    -
    1493  int i=0;
    -
    1494  for (int t=0; t<hamil.numSumTerms; t++) {
    -
    1495  hamil.termCoeffs[t] = coeffs[t];
    -
    1496  for (int q=0; q<hamil.numQubits; q++) {
    -
    1497  hamil.pauliCodes[i] = codes[i];
    -
    1498  i++;
    -
    1499  }
    -
    1500  }
    -
    1501 }
    +

    Definition at line 1504 of file QuEST.c.

    +
    1504  {
    +
    1505  validateHamilParams(hamil.numQubits, hamil.numSumTerms, __func__);
    +
    1506  validatePauliCodes(codes, hamil.numSumTerms*hamil.numQubits, __func__);
    +
    1507 
    +
    1508  int i=0;
    +
    1509  for (int t=0; t<hamil.numSumTerms; t++) {
    +
    1510  hamil.termCoeffs[t] = coeffs[t];
    +
    1511  for (int q=0; q<hamil.numQubits; q++) {
    +
    1512  hamil.pauliCodes[i] = codes[i];
    +
    1513  i++;
    +
    1514  }
    +
    1515  }
    +
    1516 }
    -

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, validateHamilParams(), and validatePauliCodes().

    +

    References PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, PauliHamil::termCoeffs, validateHamilParams(), and validatePauliCodes().

    Referenced by TEST_CASE().

    @@ -2193,15 +2199,15 @@

    Author
    Tyson Jones
    -

    Definition at line 1528 of file QuEST.c.

    -
    1528  {
    -
    1529  validateDiagOpInit(op, __func__);
    -
    1530  validateNumElems(op, startInd, numElems, __func__);
    -
    1531 
    -
    1532  agnostic_setDiagonalOpElems(op, startInd, real, imag, numElems);
    -
    1533 }
    +

    Definition at line 1543 of file QuEST.c.

    +
    1543  {
    +
    1544  validateDiagOpInit(op, __func__);
    +
    1545  validateNumElems(op, startInd, numElems, __func__);
    +
    1546 
    +
    1547  agnostic_setDiagonalOpElems(op, startInd, real, imag, numElems);
    +
    1548 }
    -

    References agnostic_setDiagonalOpElems(), validateDiagOpInit(), and validateNumElems().

    +

    References agnostic_setDiagonalOpElems(), validateDiagOpInit(), and validateNumElems().

    Referenced by TEST_CASE().

    @@ -2249,110 +2255,112 @@

    Author
    Tyson Jones
    -

    Definition at line 1516 of file QuEST.c.

    -
    1516  {
    -
    1517  validateDiagOpInit(op, __func__);
    -
    1518 
    - -
    1520 }
    +

    Definition at line 1531 of file QuEST.c.

    +
    1531  {
    +
    1532  validateDiagOpInit(op, __func__);
    +
    1533 
    + +
    1535 }
    -

    References agnostic_syncDiagonalOp(), and validateDiagOpInit().

    +

    References agnostic_syncDiagonalOp(), and validateDiagOpInit().

    Referenced by TEST_CASE().

    -
    void agnostic_destroyDiagonalOp(DiagonalOp op)
    Definition: QuEST_cpu.c:1357
    +
    void agnostic_destroyDiagonalOp(DiagonalOp op)
    Definition: QuEST_cpu.c:1368
    @ INVERSE_PRODUCT
    Definition: QuEST.h:233
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1489
    -
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    +
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1504
    +
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    @ PAULI_Z
    Definition: QuEST.h:96
    @ DISTANCE
    Definition: QuEST.h:234
    -
    int rank
    Definition: QuEST.h:363
    -
    void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
    -
    void validateHamilParams(int numQubits, int numTerms, const char *caller)
    +
    int rank
    Definition: QuEST.h:364
    +
    void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
    +
    void seedQuESTDefault(QuESTEnv *env)
    Seeds the random number generator with the (master node) current time and process ID.
    Definition: QuEST.c:1614
    +
    void validateHamilParams(int numQubits, int numTerms, const char *caller)
    void qasm_free(Qureg qureg)
    Definition: QuEST_qasm.c:887
    @ PAULI_I
    Definition: QuEST.h:96
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    -
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1516
    -
    void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    +
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1531
    +
    int numSeeds
    Definition: QuEST.h:367
    +
    void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
    @ TWOS_COMPLEMENT
    Definition: QuEST.h:269
    -
    void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
    -
    void agnostic_syncDiagonalOp(DiagonalOp op)
    Definition: QuEST_cpu.c:1362
    -
    void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
    Definition: QuEST_cpu.c:1317
    -
    void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
    +
    void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
    +
    void agnostic_syncDiagonalOp(DiagonalOp op)
    Definition: QuEST_cpu.c:1373
    +
    void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
    Definition: QuEST_cpu.c:1328
    +
    void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
    @ NORM
    Definition: QuEST.h:232
    @ SCALED_INVERSE_DISTANCE
    Definition: QuEST.h:234
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:361
    +
    Information about the environment the program is running in.
    Definition: QuEST.h:362
    @ UNSIGNED
    Definition: QuEST.h:269
    -
    PauliHamil createPauliHamilFromFile(char *fn)
    Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
    Definition: QuEST.c:1405
    -
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
    Definition: QuEST.c:1528
    -
    ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
    Definition: QuEST_common.c:661
    +
    PauliHamil createPauliHamilFromFile(char *fn)
    Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
    Definition: QuEST.c:1420
    +
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
    Definition: QuEST.c:1543
    +
    ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
    Definition: QuEST_common.c:652
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    @ INVERSE_DISTANCE
    Definition: QuEST.h:234
    #define qreal
    -
    void validateMatrixInit(ComplexMatrixN matr, const char *caller)
    -
    void validateFileOpened(int opened, char *fn, const char *caller)
    -
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:297
    +
    void validateMatrixInit(ComplexMatrixN matr, const char *caller)
    +
    void validateFileOpened(int opened, char *fn, const char *caller)
    +
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:296
    @ PAULI_X
    Definition: QuEST.h:96
    -
    DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
    Definition: QuEST_cpu.c:1335
    +
    DiagonalOp agnostic_createDiagonalOp(int numQubits, QuESTEnv env)
    Definition: QuEST_cpu.c:1346
    int numQubitsInStateVec
    Number of qubits in the state-vector - this is double the number represented for mixed states.
    Definition: QuEST.h:329
    int chunkId
    The position of the chunk of the state vector held by this process in the full state vector.
    Definition: QuEST.h:336
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:310
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:332
    qreal * termCoeffs
    The real coefficient of each Pauli product. This is an array of length PauliHamil....
    Definition: QuEST.h:283
    -
    #define getStaticComplexMatrixN(numQubits, re, im)
    Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing,...
    Definition: QuEST.h:5456
    +
    #define getStaticComplexMatrixN(numQubits, re, im)
    Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing,...
    Definition: QuEST.h:5521
    #define qcomp
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    +
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:42
    @ SCALED_PRODUCT
    Definition: QuEST.h:233
    -
    void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
    works for both statevectors and density matrices
    Definition: QuEST_cpu.c:1561
    -
    int numRanks
    Definition: QuEST.h:364
    +
    void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
    works for both statevectors and density matrices
    Definition: QuEST_cpu.c:1572
    +
    int numRanks
    Definition: QuEST.h:365
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:300
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:285
    Represents a diagonal complex operator on the full Hilbert state of a Qureg.
    Definition: QuEST.h:297
    @ PAULI_Y
    Definition: QuEST.h:96
    A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
    Definition: QuEST.h:277
    -
    void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
    +
    void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
    @ SCALED_INVERSE_SHIFTED_NORM
    Definition: QuEST.h:232
    qreal ** real
    Definition: QuEST.h:189
    -
    void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
    +
    void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
    +
    unsigned long int * seeds
    Definition: QuEST.h:366
    @ INVERSE_NORM
    Definition: QuEST.h:232
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
    -
    void validateNumQubitsInMatrix(int numQubits, const char *caller)
    +
    void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
    +
    void validateNumQubitsInMatrix(int numQubits, const char *caller)
    qreal ** imag
    Definition: QuEST.h:190
    -
    void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Definition: QuEST_cpu.c:1366
    +
    void agnostic_initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Definition: QuEST_cpu.c:1377
    @ PRODUCT
    Definition: QuEST.h:233
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:341
    -
    void validateDiagOpInit(DiagonalOp op, const char *caller)
    -
    void seedQuESTDefault()
    Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
    +
    void validateDiagOpInit(DiagonalOp op, const char *caller)
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:302
    -
    void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
    Definition: QuEST.c:1535
    +
    void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
    Definition: QuEST.c:1550
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    int numQubits
    Definition: QuEST.h:188
    -
    void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
    +
    void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
    int numQubits
    The number of qubits informing the Hilbert dimension of the Hamiltonian.
    Definition: QuEST.h:287
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:327
    long long int numAmpsTotal
    Total number of amplitudes, which are possibly distributed among machines.
    Definition: QuEST.h:334
    @ SCALED_DISTANCE
    Definition: QuEST.h:234
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:308
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1399
    -
    void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Definition: QuEST_cpu.c:4188
    -
    void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
    -
    void validateNumRanks(int numRanks, const char *caller)
    +
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1414
    +
    void agnostic_setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Definition: QuEST_cpu.c:4228
    +
    void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
    +
    void validateNumRanks(int numRanks, const char *caller)
    @ SCALED_INVERSE_SHIFTED_DISTANCE
    Definition: QuEST.h:234
    @ SCALED_NORM
    Definition: QuEST.h:232
    @ SCALED_INVERSE_PRODUCT
    Definition: QuEST.h:233
    void initZeroState(Qureg qureg)
    Initialise qureg into the zero state.
    Definition: QuEST.c:113
    void qasm_setup(Qureg *qureg)
    Definition: QuEST_qasm.c:61
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    -
    void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
    Definition: QuEST_cpu.c:1279
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1383
    -
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1503
    +
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    +
    void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
    Definition: QuEST_cpu.c:1290
    +
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1398
    +
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1518
    @ SCALED_INVERSE_NORM
    Definition: QuEST.h:232
    diff --git a/docs/group__unitary.html b/docs/group__unitary.html index d555f3069..9e299ca3b 100644 --- a/docs/group__unitary.html +++ b/docs/group__unitary.html @@ -27,7 +27,7 @@ @@ -266,21 +266,21 @@

    Definition at line 405 of file QuEST.c.

    -
    405  {
    -
    406  validateTarget(qureg, targetQubit, __func__);
    -
    407  validateUnitaryComplexPair(alpha, beta, __func__);
    -
    408 
    -
    409  statevec_compactUnitary(qureg, targetQubit, alpha, beta);
    -
    410  if (qureg.isDensityMatrix) {
    -
    411  int shift = qureg.numQubitsRepresented;
    -
    412  statevec_compactUnitary(qureg, targetQubit+shift, getConjugateScalar(alpha), getConjugateScalar(beta));
    -
    413  }
    -
    414 
    -
    415  qasm_recordCompactUnitary(qureg, alpha, beta, targetQubit);
    -
    416 }
    +

    Definition at line 404 of file QuEST.c.

    +
    404  {
    +
    405  validateTarget(qureg, targetQubit, __func__);
    +
    406  validateUnitaryComplexPair(alpha, beta, __func__);
    +
    407 
    +
    408  statevec_compactUnitary(qureg, targetQubit, alpha, beta);
    +
    409  if (qureg.isDensityMatrix) {
    +
    410  int shift = qureg.numQubitsRepresented;
    +
    411  statevec_compactUnitary(qureg, targetQubit+shift, getConjugateScalar(alpha), getConjugateScalar(beta));
    +
    412  }
    +
    413 
    +
    414  qasm_recordCompactUnitary(qureg, alpha, beta, targetQubit);
    +
    415 }
    -

    References getConjugateScalar(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordCompactUnitary(), statevec_compactUnitary(), validateTarget(), and validateUnitaryComplexPair().

    +

    References getConjugateScalar(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordCompactUnitary(), statevec_compactUnitary(), validateTarget(), and validateUnitaryComplexPair().

    Referenced by TEST_CASE().

    @@ -372,23 +372,23 @@

    Definition at line 418 of file QuEST.c.

    -
    418  {
    -
    419  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    420  validateUnitaryComplexPair(alpha, beta, __func__);
    -
    421 
    -
    422  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
    -
    423  if (qureg.isDensityMatrix) {
    -
    424  int shift = qureg.numQubitsRepresented;
    - -
    426  controlQubit+shift, targetQubit+shift,
    -
    427  getConjugateScalar(alpha), getConjugateScalar(beta));
    -
    428  }
    -
    429 
    -
    430  qasm_recordControlledCompactUnitary(qureg, alpha, beta, controlQubit, targetQubit);
    -
    431 }
    +

    Definition at line 417 of file QuEST.c.

    +
    417  {
    +
    418  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    419  validateUnitaryComplexPair(alpha, beta, __func__);
    +
    420 
    +
    421  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
    +
    422  if (qureg.isDensityMatrix) {
    +
    423  int shift = qureg.numQubitsRepresented;
    + +
    425  controlQubit+shift, targetQubit+shift,
    +
    426  getConjugateScalar(alpha), getConjugateScalar(beta));
    +
    427  }
    +
    428 
    +
    429  qasm_recordControlledCompactUnitary(qureg, alpha, beta, controlQubit, targetQubit);
    +
    430 }
    -

    References getConjugateScalar(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledCompactUnitary(), statevec_controlledCompactUnitary(), validateControlTarget(), and validateUnitaryComplexPair().

    +

    References getConjugateScalar(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledCompactUnitary(), statevec_controlledCompactUnitary(), validateControlTarget(), and validateUnitaryComplexPair().

    Referenced by TEST_CASE().

    @@ -481,25 +481,25 @@

    Author
    Tyson Jones
    -

    Definition at line 314 of file QuEST.c.

    -
    314  {
    -
    315  validateMultiControlsMultiTargets(qureg, (int[]) {ctrl}, 1, targs, numTargs, __func__);
    -
    316  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    -
    317 
    -
    318  statevec_controlledMultiQubitUnitary(qureg, ctrl, targs, numTargs, u);
    -
    319  if (qureg.isDensityMatrix) {
    -
    320  int shift = qureg.numQubitsRepresented;
    -
    321  shiftIndices(targs, numTargs, shift);
    - -
    323  statevec_controlledMultiQubitUnitary(qureg, ctrl+shift, targs, numTargs, u);
    -
    324  shiftIndices(targs, numTargs, -shift);
    - -
    326  }
    -
    327 
    -
    328  qasm_recordComment(qureg, "Here, an undisclosed controlled multi-qubit unitary was applied.");
    -
    329 }
    +

    Definition at line 313 of file QuEST.c.

    +
    313  {
    +
    314  validateMultiControlsMultiTargets(qureg, (int[]) {ctrl}, 1, targs, numTargs, __func__);
    +
    315  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    +
    316 
    +
    317  statevec_controlledMultiQubitUnitary(qureg, ctrl, targs, numTargs, u);
    +
    318  if (qureg.isDensityMatrix) {
    +
    319  int shift = qureg.numQubitsRepresented;
    +
    320  shiftIndices(targs, numTargs, shift);
    + +
    322  statevec_controlledMultiQubitUnitary(qureg, ctrl+shift, targs, numTargs, u);
    +
    323  shiftIndices(targs, numTargs, -shift);
    + +
    325  }
    +
    326 
    +
    327  qasm_recordComment(qureg, "Here, an undisclosed controlled multi-qubit unitary was applied.");
    +
    328 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_controlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitUnitaryMatrix().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_controlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -572,20 +572,20 @@

    Definition at line 525 of file QuEST.c.

    -
    525  {
    -
    526  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    527 
    -
    528  statevec_controlledNot(qureg, controlQubit, targetQubit);
    -
    529  if (qureg.isDensityMatrix) {
    -
    530  int shift = qureg.numQubitsRepresented;
    -
    531  statevec_controlledNot(qureg, controlQubit+shift, targetQubit+shift);
    -
    532  }
    -
    533 
    -
    534  qasm_recordControlledGate(qureg, GATE_SIGMA_X, controlQubit, targetQubit);
    -
    535 }
    +

    Definition at line 524 of file QuEST.c.

    +
    524  {
    +
    525  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    526 
    +
    527  statevec_controlledNot(qureg, controlQubit, targetQubit);
    +
    528  if (qureg.isDensityMatrix) {
    +
    529  int shift = qureg.numQubitsRepresented;
    +
    530  statevec_controlledNot(qureg, controlQubit+shift, targetQubit+shift);
    +
    531  }
    +
    532 
    +
    533  qasm_recordControlledGate(qureg, GATE_SIGMA_X, controlQubit, targetQubit);
    +
    534 }
    -

    References GATE_SIGMA_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledNot(), and validateControlTarget().

    +

    References GATE_SIGMA_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledNot(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -653,20 +653,20 @@

    Definition at line 564 of file QuEST.c.

    -
    564  {
    -
    565  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    566 
    -
    567  statevec_controlledPauliY(qureg, controlQubit, targetQubit);
    -
    568  if (qureg.isDensityMatrix) {
    -
    569  int shift = qureg.numQubitsRepresented;
    -
    570  statevec_controlledPauliYConj(qureg, controlQubit+shift, targetQubit+shift);
    -
    571  }
    -
    572 
    -
    573  qasm_recordControlledGate(qureg, GATE_SIGMA_Y, controlQubit, targetQubit);
    -
    574 }
    +

    Definition at line 563 of file QuEST.c.

    +
    563  {
    +
    564  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    565 
    +
    566  statevec_controlledPauliY(qureg, controlQubit, targetQubit);
    +
    567  if (qureg.isDensityMatrix) {
    +
    568  int shift = qureg.numQubitsRepresented;
    +
    569  statevec_controlledPauliYConj(qureg, controlQubit+shift, targetQubit+shift);
    +
    570  }
    +
    571 
    +
    572  qasm_recordControlledGate(qureg, GATE_SIGMA_Y, controlQubit, targetQubit);
    +
    573 }
    -

    References GATE_SIGMA_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), and validateControlTarget().

    +

    References GATE_SIGMA_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -736,20 +736,20 @@

    Author
    Tyson Jones
    -

    Definition at line 576 of file QuEST.c.

    -
    576  {
    -
    577  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
    -
    578 
    -
    579  statevec_controlledPhaseFlip(qureg, idQubit1, idQubit2);
    -
    580  if (qureg.isDensityMatrix) {
    -
    581  int shift = qureg.numQubitsRepresented;
    -
    582  statevec_controlledPhaseFlip(qureg, idQubit1+shift, idQubit2+shift);
    -
    583  }
    -
    584 
    -
    585  qasm_recordControlledGate(qureg, GATE_SIGMA_Z, idQubit1, idQubit2);
    -
    586 }
    +

    Definition at line 575 of file QuEST.c.

    +
    575  {
    +
    576  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
    +
    577 
    +
    578  statevec_controlledPhaseFlip(qureg, idQubit1, idQubit2);
    +
    579  if (qureg.isDensityMatrix) {
    +
    580  int shift = qureg.numQubitsRepresented;
    +
    581  statevec_controlledPhaseFlip(qureg, idQubit1+shift, idQubit2+shift);
    +
    582  }
    +
    583 
    +
    584  qasm_recordControlledGate(qureg, GATE_SIGMA_Z, idQubit1, idQubit2);
    +
    585 }
    -

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledPhaseFlip(), and validateControlTarget().

    +

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_controlledPhaseFlip(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -827,20 +827,20 @@

    Author
    Tyson Jones
    -

    Definition at line 499 of file QuEST.c.

    -
    499  {
    -
    500  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
    -
    501 
    -
    502  statevec_controlledPhaseShift(qureg, idQubit1, idQubit2, angle);
    -
    503  if (qureg.isDensityMatrix) {
    -
    504  int shift = qureg.numQubitsRepresented;
    -
    505  statevec_controlledPhaseShift(qureg, idQubit1+shift, idQubit2+shift, -angle);
    -
    506  }
    -
    507 
    -
    508  qasm_recordControlledParamGate(qureg, GATE_PHASE_SHIFT, idQubit1, idQubit2, angle);
    -
    509 }
    +

    Definition at line 498 of file QuEST.c.

    +
    498  {
    +
    499  validateControlTarget(qureg, idQubit1, idQubit2, __func__);
    +
    500 
    +
    501  statevec_controlledPhaseShift(qureg, idQubit1, idQubit2, angle);
    +
    502  if (qureg.isDensityMatrix) {
    +
    503  int shift = qureg.numQubitsRepresented;
    +
    504  statevec_controlledPhaseShift(qureg, idQubit1+shift, idQubit2+shift, -angle);
    +
    505  }
    +
    506 
    +
    507  qasm_recordControlledParamGate(qureg, GATE_PHASE_SHIFT, idQubit1, idQubit2, angle);
    +
    508 }
    -

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledPhaseShift(), and validateControlTarget().

    +

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledPhaseShift(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -925,21 +925,21 @@

    Author
    Tyson Jones
    -

    Definition at line 615 of file QuEST.c.

    -
    615  {
    -
    616  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    617  validateVector(axis, __func__);
    -
    618 
    -
    619  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, axis);
    -
    620  if (qureg.isDensityMatrix) {
    -
    621  int shift = qureg.numQubitsRepresented;
    -
    622  statevec_controlledRotateAroundAxisConj(qureg, controlQubit+shift, targetQubit+shift, angle, axis);
    -
    623  }
    -
    624 
    -
    625  qasm_recordControlledAxisRotation(qureg, angle, axis, controlQubit, targetQubit);
    -
    626 }
    +

    Definition at line 614 of file QuEST.c.

    +
    614  {
    +
    615  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    616  validateVector(axis, __func__);
    +
    617 
    +
    618  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, axis);
    +
    619  if (qureg.isDensityMatrix) {
    +
    620  int shift = qureg.numQubitsRepresented;
    +
    621  statevec_controlledRotateAroundAxisConj(qureg, controlQubit+shift, targetQubit+shift, angle, axis);
    +
    622  }
    +
    623 
    +
    624  qasm_recordControlledAxisRotation(qureg, angle, axis, controlQubit, targetQubit);
    +
    625 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), validateControlTarget(), and validateVector().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledAxisRotation(), statevec_controlledRotateAroundAxis(), statevec_controlledRotateAroundAxisConj(), validateControlTarget(), and validateVector().

    Referenced by TEST_CASE().

    @@ -1019,20 +1019,20 @@

    Author
    Tyson Jones
    -

    Definition at line 221 of file QuEST.c.

    -
    221  {
    -
    222  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    223 
    -
    224  statevec_controlledRotateX(qureg, controlQubit, targetQubit, angle);
    -
    225  if (qureg.isDensityMatrix) {
    -
    226  int shift = qureg.numQubitsRepresented;
    -
    227  statevec_controlledRotateX(qureg, controlQubit+shift, targetQubit+shift, -angle);
    -
    228  }
    -
    229 
    -
    230  qasm_recordControlledParamGate(qureg, GATE_ROTATE_X, controlQubit, targetQubit, angle);
    -
    231 }
    +

    Definition at line 220 of file QuEST.c.

    +
    220  {
    +
    221  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    222 
    +
    223  statevec_controlledRotateX(qureg, controlQubit, targetQubit, angle);
    +
    224  if (qureg.isDensityMatrix) {
    +
    225  int shift = qureg.numQubitsRepresented;
    +
    226  statevec_controlledRotateX(qureg, controlQubit+shift, targetQubit+shift, -angle);
    +
    227  }
    +
    228 
    +
    229  qasm_recordControlledParamGate(qureg, GATE_ROTATE_X, controlQubit, targetQubit, angle);
    +
    230 }
    -

    References GATE_ROTATE_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateX(), and validateControlTarget().

    +

    References GATE_ROTATE_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateX(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -1111,20 +1111,20 @@

    Author
    Tyson Jones
    -

    Definition at line 233 of file QuEST.c.

    -
    233  {
    -
    234  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    235 
    -
    236  statevec_controlledRotateY(qureg, controlQubit, targetQubit, angle);
    -
    237  if (qureg.isDensityMatrix) {
    -
    238  int shift = qureg.numQubitsRepresented;
    -
    239  statevec_controlledRotateY(qureg, controlQubit+shift, targetQubit+shift, angle); // rotateY is real
    -
    240  }
    -
    241 
    -
    242  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Y, controlQubit, targetQubit, angle);
    -
    243 }
    +

    Definition at line 232 of file QuEST.c.

    +
    232  {
    +
    233  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    234 
    +
    235  statevec_controlledRotateY(qureg, controlQubit, targetQubit, angle);
    +
    236  if (qureg.isDensityMatrix) {
    +
    237  int shift = qureg.numQubitsRepresented;
    +
    238  statevec_controlledRotateY(qureg, controlQubit+shift, targetQubit+shift, angle); // rotateY is real
    +
    239  }
    +
    240 
    +
    241  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Y, controlQubit, targetQubit, angle);
    +
    242 }
    -

    References GATE_ROTATE_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateY(), and validateControlTarget().

    +

    References GATE_ROTATE_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateY(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -1204,20 +1204,20 @@

    Author
    Tyson Jones
    -

    Definition at line 245 of file QuEST.c.

    -
    245  {
    -
    246  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    247 
    -
    248  statevec_controlledRotateZ(qureg, controlQubit, targetQubit, angle);
    -
    249  if (qureg.isDensityMatrix) {
    -
    250  int shift = qureg.numQubitsRepresented;
    -
    251  statevec_controlledRotateZ(qureg, controlQubit+shift, targetQubit+shift, -angle);
    -
    252  }
    -
    253 
    -
    254  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Z, controlQubit, targetQubit, angle);
    -
    255 }
    +

    Definition at line 244 of file QuEST.c.

    +
    244  {
    +
    245  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    246 
    +
    247  statevec_controlledRotateZ(qureg, controlQubit, targetQubit, angle);
    +
    248  if (qureg.isDensityMatrix) {
    +
    249  int shift = qureg.numQubitsRepresented;
    +
    250  statevec_controlledRotateZ(qureg, controlQubit+shift, targetQubit+shift, -angle);
    +
    251  }
    +
    252 
    +
    253  qasm_recordControlledParamGate(qureg, GATE_ROTATE_Z, controlQubit, targetQubit, angle);
    +
    254 }
    -

    References GATE_ROTATE_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateZ(), and validateControlTarget().

    +

    References GATE_ROTATE_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledParamGate(), statevec_controlledRotateZ(), and validateControlTarget().

    Referenced by TEST_CASE().

    @@ -1312,21 +1312,21 @@

    Author
    Tyson Jones
    -

    Definition at line 270 of file QuEST.c.

    -
    270  {
    -
    271  validateMultiControlsMultiTargets(qureg, (int[]) {controlQubit}, 1, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
    -
    272  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    -
    273 
    -
    274  statevec_controlledTwoQubitUnitary(qureg, controlQubit, targetQubit1, targetQubit2, u);
    -
    275  if (qureg.isDensityMatrix) {
    -
    276  int shift = qureg.numQubitsRepresented;
    -
    277  statevec_controlledTwoQubitUnitary(qureg, controlQubit+shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    -
    278  }
    -
    279 
    -
    280  qasm_recordComment(qureg, "Here, an undisclosed controlled 2-qubit unitary was applied.");
    -
    281 }
    +

    Definition at line 269 of file QuEST.c.

    +
    269  {
    +
    270  validateMultiControlsMultiTargets(qureg, (int[]) {controlQubit}, 1, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
    +
    271  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    +
    272 
    +
    273  statevec_controlledTwoQubitUnitary(qureg, controlQubit, targetQubit1, targetQubit2, u);
    +
    274  if (qureg.isDensityMatrix) {
    +
    275  int shift = qureg.numQubitsRepresented;
    +
    276  statevec_controlledTwoQubitUnitary(qureg, controlQubit+shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    +
    277  }
    +
    278 
    +
    279  qasm_recordComment(qureg, "Here, an undisclosed controlled 2-qubit unitary was applied.");
    +
    280 }
    -

    References getConjugateMatrix4(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_controlledTwoQubitUnitary(), validateMultiControlsMultiTargets(), and validateTwoQubitUnitaryMatrix().

    +

    References getConjugateMatrix4(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_controlledTwoQubitUnitary(), validateMultiControlsMultiTargets(), and validateTwoQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -1412,21 +1412,21 @@

    Definition at line 361 of file QuEST.c.

    -
    361  {
    -
    362  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    -
    363  validateOneQubitUnitaryMatrix(u, __func__);
    -
    364 
    -
    365  statevec_controlledUnitary(qureg, controlQubit, targetQubit, u);
    -
    366  if (qureg.isDensityMatrix) {
    -
    367  int shift = qureg.numQubitsRepresented;
    -
    368  statevec_controlledUnitary(qureg, controlQubit+shift, targetQubit+shift, getConjugateMatrix2(u));
    -
    369  }
    -
    370 
    -
    371  qasm_recordControlledUnitary(qureg, u, controlQubit, targetQubit);
    -
    372 }
    +

    Definition at line 360 of file QuEST.c.

    +
    360  {
    +
    361  validateControlTarget(qureg, controlQubit, targetQubit, __func__);
    +
    362  validateOneQubitUnitaryMatrix(u, __func__);
    +
    363 
    +
    364  statevec_controlledUnitary(qureg, controlQubit, targetQubit, u);
    +
    365  if (qureg.isDensityMatrix) {
    +
    366  int shift = qureg.numQubitsRepresented;
    +
    367  statevec_controlledUnitary(qureg, controlQubit+shift, targetQubit+shift, getConjugateMatrix2(u));
    +
    368  }
    +
    369 
    +
    370  qasm_recordControlledUnitary(qureg, u, controlQubit, targetQubit);
    +
    371 }
    -

    References getConjugateMatrix2(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledUnitary(), statevec_controlledUnitary(), validateControlTarget(), and validateOneQubitUnitaryMatrix().

    +

    References getConjugateMatrix2(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledUnitary(), statevec_controlledUnitary(), validateControlTarget(), and validateOneQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -1485,19 +1485,19 @@

    Definition at line 177 of file QuEST.c.

    -
    177  {
    -
    178  validateTarget(qureg, targetQubit, __func__);
    -
    179 
    -
    180  statevec_hadamard(qureg, targetQubit);
    -
    181  if (qureg.isDensityMatrix) {
    -
    182  statevec_hadamard(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    183  }
    -
    184 
    -
    185  qasm_recordGate(qureg, GATE_HADAMARD, targetQubit);
    -
    186 }
    +

    Definition at line 176 of file QuEST.c.

    +
    176  {
    +
    177  validateTarget(qureg, targetQubit, __func__);
    +
    178 
    +
    179  statevec_hadamard(qureg, targetQubit);
    +
    180  if (qureg.isDensityMatrix) {
    +
    181  statevec_hadamard(qureg, targetQubit+qureg.numQubitsRepresented);
    +
    182  }
    +
    183 
    +
    184  qasm_recordGate(qureg, GATE_HADAMARD, targetQubit);
    +
    185 }
    -

    References GATE_HADAMARD, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_hadamard(), and validateTarget().

    +

    References GATE_HADAMARD, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_hadamard(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -1598,22 +1598,22 @@

    Author
    Tyson Jones
    -

    Definition at line 550 of file QuEST.c.

    -
    550  {
    -
    551  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
    -
    552 
    -
    553  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
    -
    554  long long int targMask = getQubitBitMask(targs, numTargs);
    -
    555  statevec_multiControlledMultiQubitNot(qureg, ctrlMask, targMask);
    -
    556  if (qureg.isDensityMatrix) {
    -
    557  int shift = qureg.numQubitsRepresented;
    -
    558  statevec_multiControlledMultiQubitNot(qureg, ctrlMask<<shift, targMask<<shift);
    -
    559  }
    -
    560 
    -
    561  qasm_recordMultiControlledMultiQubitNot(qureg, ctrls, numCtrls, targs, numTargs);
    -
    562 }
    +

    Definition at line 549 of file QuEST.c.

    +
    549  {
    +
    550  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
    +
    551 
    +
    552  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
    +
    553  long long int targMask = getQubitBitMask(targs, numTargs);
    +
    554  statevec_multiControlledMultiQubitNot(qureg, ctrlMask, targMask);
    +
    555  if (qureg.isDensityMatrix) {
    +
    556  int shift = qureg.numQubitsRepresented;
    +
    557  statevec_multiControlledMultiQubitNot(qureg, ctrlMask<<shift, targMask<<shift);
    +
    558  }
    +
    559 
    +
    560  qasm_recordMultiControlledMultiQubitNot(qureg, ctrls, numCtrls, targs, numTargs);
    +
    561 }
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNot(), and validateMultiControlsMultiTargets().

    +

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNot(), and validateMultiControlsMultiTargets().

    Referenced by TEST_CASE().

    @@ -1724,26 +1724,26 @@

    Author
    Tyson Jones
    -

    Definition at line 331 of file QuEST.c.

    -
    331  {
    -
    332  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
    -
    333  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    -
    334 
    -
    335  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
    -
    336  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
    -
    337  if (qureg.isDensityMatrix) {
    -
    338  int shift = qureg.numQubitsRepresented;
    -
    339  shiftIndices(targs, numTargs, shift);
    - -
    341  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask<<shift, targs, numTargs, u);
    -
    342  shiftIndices(targs, numTargs, -shift);
    - -
    344  }
    -
    345 
    -
    346  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled multi-qubit unitary was applied.");
    -
    347 }
    +

    Definition at line 330 of file QuEST.c.

    +
    330  {
    +
    331  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
    +
    332  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    +
    333 
    +
    334  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
    +
    335  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
    +
    336  if (qureg.isDensityMatrix) {
    +
    337  int shift = qureg.numQubitsRepresented;
    +
    338  shiftIndices(targs, numTargs, shift);
    + +
    340  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask<<shift, targs, numTargs, u);
    +
    341  shiftIndices(targs, numTargs, -shift);
    + +
    343  }
    +
    344 
    +
    345  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled multi-qubit unitary was applied.");
    +
    346 }
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitUnitaryMatrix().

    +

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -1877,29 +1877,29 @@

    Author
    Tyson Jones
    -

    Definition at line 706 of file QuEST.c.

    -
    706  {
    -
    707  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
    -
    708  validatePauliCodes(targetPaulis, numTargets, __func__);
    -
    709 
    -
    710  int conj=0;
    -
    711  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
    -
    712  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask, targetQubits, targetPaulis, numTargets, angle, conj);
    -
    713  if (qureg.isDensityMatrix) {
    -
    714  conj = 1;
    -
    715  int shift = qureg.numQubitsRepresented;
    -
    716  shiftIndices(targetQubits, numTargets, shift);
    -
    717  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask<<shift, targetQubits, targetPaulis, numTargets, angle, conj);
    -
    718  shiftIndices(targetQubits, numTargets, -shift);
    -
    719  }
    -
    720 
    -
    721  // @TODO: create actual QASM
    -
    722  qasm_recordComment(qureg,
    -
    723  "Here a %d-control %d-target multiControlledMultiRotatePauli of angle %g was performed (QASM not yet implemented)",
    -
    724  numControls, numTargets, angle);
    -
    725 }
    +

    Definition at line 705 of file QuEST.c.

    +
    705  {
    +
    706  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
    +
    707  validatePauliCodes(targetPaulis, numTargets, __func__);
    +
    708 
    +
    709  int conj=0;
    +
    710  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
    +
    711  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask, targetQubits, targetPaulis, numTargets, angle, conj);
    +
    712  if (qureg.isDensityMatrix) {
    +
    713  conj = 1;
    +
    714  int shift = qureg.numQubitsRepresented;
    +
    715  shiftIndices(targetQubits, numTargets, shift);
    +
    716  statevec_multiControlledMultiRotatePauli(qureg, ctrlMask<<shift, targetQubits, targetPaulis, numTargets, angle, conj);
    +
    717  shiftIndices(targetQubits, numTargets, -shift);
    +
    718  }
    +
    719 
    +
    720  // @TODO: create actual QASM
    +
    721  qasm_recordComment(qureg,
    +
    722  "Here a %d-control %d-target multiControlledMultiRotatePauli of angle %g was performed (QASM not yet implemented)",
    +
    723  numControls, numTargets, angle);
    +
    724 }
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), shiftIndices(), statevec_multiControlledMultiRotatePauli(), validateMultiControlsMultiTargets(), and validatePauliCodes().

    +

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), shiftIndices(), statevec_multiControlledMultiRotatePauli(), validateMultiControlsMultiTargets(), and validatePauliCodes().

    Referenced by TEST_CASE().

    @@ -2006,25 +2006,25 @@

    Author
    Tyson Jones
    -

    Definition at line 669 of file QuEST.c.

    -
    669  {
    -
    670  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
    -
    671 
    -
    672  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
    -
    673  long long int targMask = getQubitBitMask(targetQubits, numTargets);
    -
    674  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, angle);
    -
    675  if (qureg.isDensityMatrix) {
    -
    676  int shift = qureg.numQubitsRepresented;
    -
    677  statevec_multiControlledMultiRotateZ(qureg, ctrlMask<<shift, targMask<<shift, - angle);
    -
    678  }
    -
    679 
    -
    680  // @TODO: create actual QASM
    -
    681  qasm_recordComment(qureg,
    -
    682  "Here a %d-control %d-target multiControlledMultiRotateZ of angle %g was performed (QASM not yet implemented)",
    -
    683  numControls, numTargets, angle);
    -
    684 }
    +

    Definition at line 668 of file QuEST.c.

    +
    668  {
    +
    669  validateMultiControlsMultiTargets(qureg, controlQubits, numControls, targetQubits, numTargets, __func__);
    +
    670 
    +
    671  long long int ctrlMask = getQubitBitMask(controlQubits, numControls);
    +
    672  long long int targMask = getQubitBitMask(targetQubits, numTargets);
    +
    673  statevec_multiControlledMultiRotateZ(qureg, ctrlMask, targMask, angle);
    +
    674  if (qureg.isDensityMatrix) {
    +
    675  int shift = qureg.numQubitsRepresented;
    +
    676  statevec_multiControlledMultiRotateZ(qureg, ctrlMask<<shift, targMask<<shift, - angle);
    +
    677  }
    +
    678 
    +
    679  // @TODO: create actual QASM
    +
    680  qasm_recordComment(qureg,
    +
    681  "Here a %d-control %d-target multiControlledMultiRotateZ of angle %g was performed (QASM not yet implemented)",
    +
    682  numControls, numTargets, angle);
    +
    683 }
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiControlledMultiRotateZ(), and validateMultiControlsMultiTargets().

    +

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiControlledMultiRotateZ(), and validateMultiControlsMultiTargets().

    Referenced by TEST_CASE().

    @@ -2091,22 +2091,22 @@

    Author
    Tyson Jones
    -

    Definition at line 588 of file QuEST.c.

    -
    588  {
    -
    589  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
    -
    590 
    -
    591  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
    -
    592  if (qureg.isDensityMatrix) {
    -
    593  int shift = qureg.numQubitsRepresented;
    -
    594  shiftIndices(controlQubits, numControlQubits, shift);
    -
    595  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
    -
    596  shiftIndices(controlQubits, numControlQubits, -shift);
    -
    597  }
    -
    598 
    -
    599  qasm_recordMultiControlledGate(qureg, GATE_SIGMA_Z, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1]);
    -
    600 }
    +

    Definition at line 587 of file QuEST.c.

    +
    587  {
    +
    588  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
    +
    589 
    +
    590  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
    +
    591  if (qureg.isDensityMatrix) {
    +
    592  int shift = qureg.numQubitsRepresented;
    +
    593  shiftIndices(controlQubits, numControlQubits, shift);
    +
    594  statevec_multiControlledPhaseFlip(qureg, controlQubits, numControlQubits);
    +
    595  shiftIndices(controlQubits, numControlQubits, -shift);
    +
    596  }
    +
    597 
    +
    598  qasm_recordMultiControlledGate(qureg, GATE_SIGMA_Z, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1]);
    +
    599 }
    -

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledGate(), shiftIndices(), statevec_multiControlledPhaseFlip(), and validateMultiQubits().

    +

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledGate(), shiftIndices(), statevec_multiControlledPhaseFlip(), and validateMultiQubits().

    Referenced by TEST_CASE().

    @@ -2183,22 +2183,22 @@

    Author
    Tyson Jones
    -

    Definition at line 511 of file QuEST.c.

    -
    511  {
    -
    512  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
    -
    513 
    -
    514  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, angle);
    -
    515  if (qureg.isDensityMatrix) {
    -
    516  int shift = qureg.numQubitsRepresented;
    -
    517  shiftIndices(controlQubits, numControlQubits, shift);
    -
    518  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, -angle);
    -
    519  shiftIndices(controlQubits, numControlQubits, -shift);
    -
    520  }
    -
    521 
    -
    522  qasm_recordMultiControlledParamGate(qureg, GATE_PHASE_SHIFT, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1], angle);
    -
    523 }
    +

    Definition at line 510 of file QuEST.c.

    +
    510  {
    +
    511  validateMultiQubits(qureg, controlQubits, numControlQubits, __func__);
    +
    512 
    +
    513  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, angle);
    +
    514  if (qureg.isDensityMatrix) {
    +
    515  int shift = qureg.numQubitsRepresented;
    +
    516  shiftIndices(controlQubits, numControlQubits, shift);
    +
    517  statevec_multiControlledPhaseShift(qureg, controlQubits, numControlQubits, -angle);
    +
    518  shiftIndices(controlQubits, numControlQubits, -shift);
    +
    519  }
    +
    520 
    +
    521  qasm_recordMultiControlledParamGate(qureg, GATE_PHASE_SHIFT, controlQubits, numControlQubits-1, controlQubits[numControlQubits-1], angle);
    +
    522 }
    -

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledParamGate(), shiftIndices(), statevec_multiControlledPhaseShift(), and validateMultiQubits().

    +

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledParamGate(), shiftIndices(), statevec_multiControlledPhaseShift(), and validateMultiQubits().

    Referenced by TEST_CASE().

    @@ -2301,22 +2301,22 @@

    Author
    Tyson Jones
    -

    Definition at line 283 of file QuEST.c.

    -
    283  {
    -
    284  validateMultiControlsMultiTargets(qureg, controlQubits, numControlQubits, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
    -
    285  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    -
    286 
    -
    287  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    -
    288  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask, targetQubit1, targetQubit2, u);
    -
    289  if (qureg.isDensityMatrix) {
    -
    290  int shift = qureg.numQubitsRepresented;
    -
    291  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask<<shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    -
    292  }
    -
    293 
    -
    294  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled 2-qubit unitary was applied.");
    -
    295 }
    +

    Definition at line 282 of file QuEST.c.

    +
    282  {
    +
    283  validateMultiControlsMultiTargets(qureg, controlQubits, numControlQubits, (int[]) {targetQubit1, targetQubit2}, 2, __func__);
    +
    284  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    +
    285 
    +
    286  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    +
    287  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask, targetQubit1, targetQubit2, u);
    +
    288  if (qureg.isDensityMatrix) {
    +
    289  int shift = qureg.numQubitsRepresented;
    +
    290  statevec_multiControlledTwoQubitUnitary(qureg, ctrlQubitsMask<<shift, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    +
    291  }
    +
    292 
    +
    293  qasm_recordComment(qureg, "Here, an undisclosed multi-controlled 2-qubit unitary was applied.");
    +
    294 }
    -

    References getConjugateMatrix4(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiControlledTwoQubitUnitary(), validateMultiControlsMultiTargets(), and validateTwoQubitUnitaryMatrix().

    +

    References getConjugateMatrix4(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiControlledTwoQubitUnitary(), validateMultiControlsMultiTargets(), and validateTwoQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -2411,23 +2411,23 @@

    Definition at line 374 of file QuEST.c.

    -
    374  {
    -
    375  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
    -
    376  validateOneQubitUnitaryMatrix(u, __func__);
    -
    377 
    -
    378  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    -
    379  long long int ctrlFlipMask = 0;
    -
    380  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
    -
    381  if (qureg.isDensityMatrix) {
    -
    382  int shift = qureg.numQubitsRepresented;
    -
    383  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
    -
    384  }
    -
    385 
    -
    386  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
    -
    387 }
    +

    Definition at line 373 of file QuEST.c.

    +
    373  {
    +
    374  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
    +
    375  validateOneQubitUnitaryMatrix(u, __func__);
    +
    376 
    +
    377  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    +
    378  long long int ctrlFlipMask = 0;
    +
    379  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
    +
    380  if (qureg.isDensityMatrix) {
    +
    381  int shift = qureg.numQubitsRepresented;
    +
    382  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
    +
    383  }
    +
    384 
    +
    385  qasm_recordMultiControlledUnitary(qureg, u, controlQubits, numControlQubits, targetQubit);
    +
    386 }
    -

    References getConjugateMatrix2(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledUnitary(), statevec_multiControlledUnitary(), validateMultiControlsTarget(), and validateOneQubitUnitaryMatrix().

    +

    References getConjugateMatrix2(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledUnitary(), statevec_multiControlledUnitary(), validateMultiControlsTarget(), and validateOneQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -2512,21 +2512,21 @@

    Author
    Tyson Jones
    -

    Definition at line 537 of file QuEST.c.

    -
    537  {
    -
    538  validateMultiTargets(qureg, targs, numTargs, __func__);
    -
    539 
    -
    540  long long int targMask = getQubitBitMask(targs, numTargs);
    -
    541  statevec_multiControlledMultiQubitNot(qureg, 0, targMask);
    -
    542  if (qureg.isDensityMatrix) {
    -
    543  int shift = qureg.numQubitsRepresented;
    -
    544  statevec_multiControlledMultiQubitNot(qureg, 0, targMask<<shift);
    -
    545  }
    -
    546 
    -
    547  qasm_recordMultiControlledMultiQubitNot(qureg, NULL, 0, targs, numTargs);
    -
    548 }
    +

    Definition at line 536 of file QuEST.c.

    +
    536  {
    +
    537  validateMultiTargets(qureg, targs, numTargs, __func__);
    +
    538 
    +
    539  long long int targMask = getQubitBitMask(targs, numTargs);
    +
    540  statevec_multiControlledMultiQubitNot(qureg, 0, targMask);
    +
    541  if (qureg.isDensityMatrix) {
    +
    542  int shift = qureg.numQubitsRepresented;
    +
    543  statevec_multiControlledMultiQubitNot(qureg, 0, targMask<<shift);
    +
    544  }
    +
    545 
    +
    546  qasm_recordMultiControlledMultiQubitNot(qureg, NULL, 0, targs, numTargs);
    +
    547 }
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNot(), and validateMultiTargets().

    +

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNot(), and validateMultiTargets().

    Referenced by TEST_CASE().

    @@ -2616,25 +2616,25 @@

    Author
    Tyson Jones
    -

    Definition at line 297 of file QuEST.c.

    -
    297  {
    -
    298  validateMultiTargets(qureg, targs, numTargs, __func__);
    -
    299  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    -
    300 
    -
    301  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    -
    302  if (qureg.isDensityMatrix) {
    -
    303  int shift = qureg.numQubitsRepresented;
    -
    304  shiftIndices(targs, numTargs, shift);
    - -
    306  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    -
    307  shiftIndices(targs, numTargs, -shift);
    - -
    309  }
    -
    310 
    -
    311  qasm_recordComment(qureg, "Here, an undisclosed multi-qubit unitary was applied.");
    -
    312 }
    +

    Definition at line 296 of file QuEST.c.

    +
    296  {
    +
    297  validateMultiTargets(qureg, targs, numTargs, __func__);
    +
    298  validateMultiQubitUnitaryMatrix(qureg, u, numTargs, __func__);
    +
    299 
    +
    300  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    +
    301  if (qureg.isDensityMatrix) {
    +
    302  int shift = qureg.numQubitsRepresented;
    +
    303  shiftIndices(targs, numTargs, shift);
    + +
    305  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
    +
    306  shiftIndices(targs, numTargs, -shift);
    + +
    308  }
    +
    309 
    +
    310  qasm_recordComment(qureg, "Here, an undisclosed multi-qubit unitary was applied.");
    +
    311 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_multiQubitUnitary(), validateMultiQubitUnitaryMatrix(), and validateMultiTargets().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), setConjugateMatrixN(), shiftIndices(), statevec_multiQubitUnitary(), validateMultiQubitUnitaryMatrix(), and validateMultiTargets().

    Referenced by TEST_CASE().

    @@ -2735,30 +2735,30 @@

    Author
    Tyson Jones
    -

    Definition at line 686 of file QuEST.c.

    -
    686  {
    -
    687  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
    -
    688  validatePauliCodes(targetPaulis, numTargets, __func__);
    -
    689 
    -
    690  int conj=0;
    -
    691  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
    -
    692  if (qureg.isDensityMatrix) {
    -
    693  conj = 1;
    -
    694  int shift = qureg.numQubitsRepresented;
    -
    695  shiftIndices(targetQubits, numTargets, shift);
    -
    696  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
    -
    697  shiftIndices(targetQubits, numTargets, -shift);
    -
    698  }
    -
    699 
    -
    700  // @TODO: create actual QASM
    -
    701  qasm_recordComment(qureg,
    -
    702  "Here a %d-qubit multiRotatePauli of angle %g was performed (QASM not yet implemented)",
    -
    703  numTargets, angle);
    -
    704 }
    +

    Definition at line 685 of file QuEST.c.

    +
    685  {
    +
    686  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
    +
    687  validatePauliCodes(targetPaulis, numTargets, __func__);
    +
    688 
    +
    689  int conj=0;
    +
    690  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
    +
    691  if (qureg.isDensityMatrix) {
    +
    692  conj = 1;
    +
    693  int shift = qureg.numQubitsRepresented;
    +
    694  shiftIndices(targetQubits, numTargets, shift);
    +
    695  statevec_multiRotatePauli(qureg, targetQubits, targetPaulis, numTargets, angle, conj);
    +
    696  shiftIndices(targetQubits, numTargets, -shift);
    +
    697  }
    +
    698 
    +
    699  // @TODO: create actual QASM
    +
    700  qasm_recordComment(qureg,
    +
    701  "Here a %d-qubit multiRotatePauli of angle %g was performed (QASM not yet implemented)",
    +
    702  numTargets, angle);
    +
    703 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), shiftIndices(), statevec_multiRotatePauli(), validateMultiTargets(), and validatePauliCodes().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), shiftIndices(), statevec_multiRotatePauli(), validateMultiTargets(), and validatePauliCodes().

    -

    Referenced by TEST_CASE().

    +

    Referenced by TEST_CASE().

    @@ -2842,24 +2842,24 @@

    Author
    Tyson Jones
    -

    Definition at line 653 of file QuEST.c.

    -
    653  {
    -
    654  validateMultiTargets(qureg, qubits, numQubits, __func__);
    -
    655 
    -
    656  long long int mask = getQubitBitMask(qubits, numQubits);
    -
    657  statevec_multiRotateZ(qureg, mask, angle);
    -
    658  if (qureg.isDensityMatrix) {
    -
    659  int shift = qureg.numQubitsRepresented;
    -
    660  statevec_multiRotateZ(qureg, mask << shift, -angle);
    -
    661  }
    -
    662 
    -
    663  // @TODO: create actual QASM
    -
    664  qasm_recordComment(qureg,
    -
    665  "Here a %d-qubit multiRotateZ of angle %g was performed (QASM not yet implemented)",
    -
    666  numQubits, angle);
    -
    667 }
    +

    Definition at line 652 of file QuEST.c.

    +
    652  {
    +
    653  validateMultiTargets(qureg, qubits, numQubits, __func__);
    +
    654 
    +
    655  long long int mask = getQubitBitMask(qubits, numQubits);
    +
    656  statevec_multiRotateZ(qureg, mask, angle);
    +
    657  if (qureg.isDensityMatrix) {
    +
    658  int shift = qureg.numQubitsRepresented;
    +
    659  statevec_multiRotateZ(qureg, mask << shift, -angle);
    +
    660  }
    +
    661 
    +
    662  // @TODO: create actual QASM
    +
    663  qasm_recordComment(qureg,
    +
    664  "Here a %d-qubit multiRotateZ of angle %g was performed (QASM not yet implemented)",
    +
    665  numQubits, angle);
    +
    666 }
    -

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiRotateZ(), and validateMultiTargets().

    +

    References getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_multiRotateZ(), and validateMultiTargets().

    Referenced by TEST_CASE().

    @@ -2959,24 +2959,24 @@

    Author
    Tyson Jones
    -

    Definition at line 389 of file QuEST.c.

    -
    389  {
    -
    390  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
    -
    391  validateOneQubitUnitaryMatrix(u, __func__);
    -
    392  validateControlState(controlState, numControlQubits, __func__);
    -
    393 
    -
    394  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    -
    395  long long int ctrlFlipMask = getControlFlipMask(controlQubits, controlState, numControlQubits);
    -
    396  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
    -
    397  if (qureg.isDensityMatrix) {
    -
    398  int shift = qureg.numQubitsRepresented;
    -
    399  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
    -
    400  }
    -
    401 
    -
    402  qasm_recordMultiStateControlledUnitary(qureg, u, controlQubits, controlState, numControlQubits, targetQubit);
    -
    403 }
    +

    Definition at line 388 of file QuEST.c.

    +
    388  {
    +
    389  validateMultiControlsTarget(qureg, controlQubits, numControlQubits, targetQubit, __func__);
    +
    390  validateOneQubitUnitaryMatrix(u, __func__);
    +
    391  validateControlState(controlState, numControlQubits, __func__);
    +
    392 
    +
    393  long long int ctrlQubitsMask = getQubitBitMask(controlQubits, numControlQubits);
    +
    394  long long int ctrlFlipMask = getControlFlipMask(controlQubits, controlState, numControlQubits);
    +
    395  statevec_multiControlledUnitary(qureg, ctrlQubitsMask, ctrlFlipMask, targetQubit, u);
    +
    396  if (qureg.isDensityMatrix) {
    +
    397  int shift = qureg.numQubitsRepresented;
    +
    398  statevec_multiControlledUnitary(qureg, ctrlQubitsMask<<shift, ctrlFlipMask<<shift, targetQubit+shift, getConjugateMatrix2(u));
    +
    399  }
    +
    400 
    +
    401  qasm_recordMultiStateControlledUnitary(qureg, u, controlQubits, controlState, numControlQubits, targetQubit);
    +
    402 }
    -

    References getConjugateMatrix2(), getControlFlipMask(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiStateControlledUnitary(), statevec_multiControlledUnitary(), validateControlState(), validateMultiControlsTarget(), and validateOneQubitUnitaryMatrix().

    +

    References getConjugateMatrix2(), getControlFlipMask(), getQubitBitMask(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiStateControlledUnitary(), statevec_multiControlledUnitary(), validateControlState(), validateMultiControlsTarget(), and validateOneQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -3044,19 +3044,19 @@

    Definition at line 433 of file QuEST.c.

    -
    433  {
    -
    434  validateTarget(qureg, targetQubit, __func__);
    -
    435 
    -
    436  statevec_pauliX(qureg, targetQubit);
    -
    437  if (qureg.isDensityMatrix) {
    -
    438  statevec_pauliX(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    439  }
    -
    440 
    -
    441  qasm_recordGate(qureg, GATE_SIGMA_X, targetQubit);
    -
    442 }
    +

    Definition at line 432 of file QuEST.c.

    +
    432  {
    +
    433  validateTarget(qureg, targetQubit, __func__);
    +
    434 
    +
    435  statevec_pauliX(qureg, targetQubit);
    +
    436  if (qureg.isDensityMatrix) {
    +
    437  statevec_pauliX(qureg, targetQubit+qureg.numQubitsRepresented);
    +
    438  }
    +
    439 
    +
    440  qasm_recordGate(qureg, GATE_SIGMA_X, targetQubit);
    +
    441 }
    -

    References GATE_SIGMA_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliX(), and validateTarget().

    +

    References GATE_SIGMA_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliX(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3121,19 +3121,19 @@

    Definition at line 444 of file QuEST.c.

    -
    444  {
    -
    445  validateTarget(qureg, targetQubit, __func__);
    -
    446 
    -
    447  statevec_pauliY(qureg, targetQubit);
    -
    448  if (qureg.isDensityMatrix) {
    -
    449  statevec_pauliYConj(qureg, targetQubit + qureg.numQubitsRepresented);
    -
    450  }
    -
    451 
    -
    452  qasm_recordGate(qureg, GATE_SIGMA_Y, targetQubit);
    -
    453 }
    +

    Definition at line 443 of file QuEST.c.

    +
    443  {
    +
    444  validateTarget(qureg, targetQubit, __func__);
    +
    445 
    +
    446  statevec_pauliY(qureg, targetQubit);
    +
    447  if (qureg.isDensityMatrix) {
    +
    448  statevec_pauliYConj(qureg, targetQubit + qureg.numQubitsRepresented);
    +
    449  }
    +
    450 
    +
    451  qasm_recordGate(qureg, GATE_SIGMA_Y, targetQubit);
    +
    452 }
    -

    References GATE_SIGMA_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliY(), statevec_pauliYConj(), and validateTarget().

    +

    References GATE_SIGMA_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliY(), statevec_pauliYConj(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3201,19 +3201,19 @@

    Definition at line 455 of file QuEST.c.

    -
    455  {
    -
    456  validateTarget(qureg, targetQubit, __func__);
    -
    457 
    -
    458  statevec_pauliZ(qureg, targetQubit);
    -
    459  if (qureg.isDensityMatrix) {
    -
    460  statevec_pauliZ(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    461  }
    -
    462 
    -
    463  qasm_recordGate(qureg, GATE_SIGMA_Z, targetQubit);
    -
    464 }
    +

    Definition at line 454 of file QuEST.c.

    +
    454  {
    +
    455  validateTarget(qureg, targetQubit, __func__);
    +
    456 
    +
    457  statevec_pauliZ(qureg, targetQubit);
    +
    458  if (qureg.isDensityMatrix) {
    +
    459  statevec_pauliZ(qureg, targetQubit+qureg.numQubitsRepresented);
    +
    460  }
    +
    461 
    +
    462  qasm_recordGate(qureg, GATE_SIGMA_Z, targetQubit);
    +
    463 }
    -

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliZ(), and validateTarget().

    +

    References GATE_SIGMA_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_pauliZ(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3285,19 +3285,19 @@

    Author
    Tyson Jones
    -

    Definition at line 488 of file QuEST.c.

    -
    488  {
    -
    489  validateTarget(qureg, targetQubit, __func__);
    -
    490 
    -
    491  statevec_phaseShift(qureg, targetQubit, angle);
    -
    492  if (qureg.isDensityMatrix) {
    -
    493  statevec_phaseShift(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    -
    494  }
    -
    495 
    -
    496  qasm_recordParamGate(qureg, GATE_PHASE_SHIFT, targetQubit, angle);
    -
    497 }
    +

    Definition at line 487 of file QuEST.c.

    +
    487  {
    +
    488  validateTarget(qureg, targetQubit, __func__);
    +
    489 
    +
    490  statevec_phaseShift(qureg, targetQubit, angle);
    +
    491  if (qureg.isDensityMatrix) {
    +
    492  statevec_phaseShift(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    +
    493  }
    +
    494 
    +
    495  qasm_recordParamGate(qureg, GATE_PHASE_SHIFT, targetQubit, angle);
    +
    496 }
    -

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_phaseShift(), and validateTarget().

    +

    References GATE_PHASE_SHIFT, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_phaseShift(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3377,21 +3377,21 @@

    Definition at line 602 of file QuEST.c.

    -
    602  {
    -
    603  validateTarget(qureg, rotQubit, __func__);
    -
    604  validateVector(axis, __func__);
    -
    605 
    -
    606  statevec_rotateAroundAxis(qureg, rotQubit, angle, axis);
    -
    607  if (qureg.isDensityMatrix) {
    -
    608  int shift = qureg.numQubitsRepresented;
    -
    609  statevec_rotateAroundAxisConj(qureg, rotQubit+shift, angle, axis);
    -
    610  }
    -
    611 
    -
    612  qasm_recordAxisRotation(qureg, angle, axis, rotQubit);
    -
    613 }
    +

    Definition at line 601 of file QuEST.c.

    +
    601  {
    +
    602  validateTarget(qureg, rotQubit, __func__);
    +
    603  validateVector(axis, __func__);
    +
    604 
    +
    605  statevec_rotateAroundAxis(qureg, rotQubit, angle, axis);
    +
    606  if (qureg.isDensityMatrix) {
    +
    607  int shift = qureg.numQubitsRepresented;
    +
    608  statevec_rotateAroundAxisConj(qureg, rotQubit+shift, angle, axis);
    +
    609  }
    +
    610 
    +
    611  qasm_recordAxisRotation(qureg, angle, axis, rotQubit);
    +
    612 }
    -

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordAxisRotation(), statevec_rotateAroundAxis(), statevec_rotateAroundAxisConj(), validateTarget(), and validateVector().

    +

    References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordAxisRotation(), statevec_rotateAroundAxis(), statevec_rotateAroundAxisConj(), validateTarget(), and validateVector().

    Referenced by TEST_CASE().

    @@ -3466,19 +3466,19 @@

    Definition at line 188 of file QuEST.c.

    -
    188  {
    -
    189  validateTarget(qureg, targetQubit, __func__);
    -
    190 
    -
    191  statevec_rotateX(qureg, targetQubit, angle);
    -
    192  if (qureg.isDensityMatrix) {
    -
    193  statevec_rotateX(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    -
    194  }
    -
    195 
    -
    196  qasm_recordParamGate(qureg, GATE_ROTATE_X, targetQubit, angle);
    -
    197 }
    +

    Definition at line 187 of file QuEST.c.

    +
    187  {
    +
    188  validateTarget(qureg, targetQubit, __func__);
    +
    189 
    +
    190  statevec_rotateX(qureg, targetQubit, angle);
    +
    191  if (qureg.isDensityMatrix) {
    +
    192  statevec_rotateX(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    +
    193  }
    +
    194 
    +
    195  qasm_recordParamGate(qureg, GATE_ROTATE_X, targetQubit, angle);
    +
    196 }
    -

    References GATE_ROTATE_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateX(), and validateTarget().

    +

    References GATE_ROTATE_X, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateX(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3550,19 +3550,19 @@

    Definition at line 199 of file QuEST.c.

    -
    199  {
    -
    200  validateTarget(qureg, targetQubit, __func__);
    -
    201 
    -
    202  statevec_rotateY(qureg, targetQubit, angle);
    -
    203  if (qureg.isDensityMatrix) {
    -
    204  statevec_rotateY(qureg, targetQubit+qureg.numQubitsRepresented, angle);
    -
    205  }
    -
    206 
    -
    207  qasm_recordParamGate(qureg, GATE_ROTATE_Y, targetQubit, angle);
    -
    208 }
    +

    Definition at line 198 of file QuEST.c.

    +
    198  {
    +
    199  validateTarget(qureg, targetQubit, __func__);
    +
    200 
    +
    201  statevec_rotateY(qureg, targetQubit, angle);
    +
    202  if (qureg.isDensityMatrix) {
    +
    203  statevec_rotateY(qureg, targetQubit+qureg.numQubitsRepresented, angle);
    +
    204  }
    +
    205 
    +
    206  qasm_recordParamGate(qureg, GATE_ROTATE_Y, targetQubit, angle);
    +
    207 }
    -

    References GATE_ROTATE_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateY(), and validateTarget().

    +

    References GATE_ROTATE_Y, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateY(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3639,19 +3639,19 @@

    Definition at line 210 of file QuEST.c.

    -
    210  {
    -
    211  validateTarget(qureg, targetQubit, __func__);
    -
    212 
    -
    213  statevec_rotateZ(qureg, targetQubit, angle);
    -
    214  if (qureg.isDensityMatrix) {
    -
    215  statevec_rotateZ(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    -
    216  }
    -
    217 
    -
    218  qasm_recordParamGate(qureg, GATE_ROTATE_Z, targetQubit, angle);
    -
    219 }
    +

    Definition at line 209 of file QuEST.c.

    +
    209  {
    +
    210  validateTarget(qureg, targetQubit, __func__);
    +
    211 
    +
    212  statevec_rotateZ(qureg, targetQubit, angle);
    +
    213  if (qureg.isDensityMatrix) {
    +
    214  statevec_rotateZ(qureg, targetQubit+qureg.numQubitsRepresented, -angle);
    +
    215  }
    +
    216 
    +
    217  qasm_recordParamGate(qureg, GATE_ROTATE_Z, targetQubit, angle);
    +
    218 }
    -

    References GATE_ROTATE_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateZ(), and validateTarget().

    +

    References GATE_ROTATE_Z, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordParamGate(), statevec_rotateZ(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3714,19 +3714,19 @@

    Definition at line 466 of file QuEST.c.

    -
    466  {
    -
    467  validateTarget(qureg, targetQubit, __func__);
    -
    468 
    -
    469  statevec_sGate(qureg, targetQubit);
    -
    470  if (qureg.isDensityMatrix) {
    -
    471  statevec_sGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    472  }
    -
    473 
    -
    474  qasm_recordGate(qureg, GATE_S, targetQubit);
    -
    475 }
    +

    Definition at line 465 of file QuEST.c.

    +
    465  {
    +
    466  validateTarget(qureg, targetQubit, __func__);
    +
    467 
    +
    468  statevec_sGate(qureg, targetQubit);
    +
    469  if (qureg.isDensityMatrix) {
    +
    470  statevec_sGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
    +
    471  }
    +
    472 
    +
    473  qasm_recordGate(qureg, GATE_S, targetQubit);
    +
    474 }
    -

    References GATE_S, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_sGate(), statevec_sGateConj(), and validateTarget().

    +

    References GATE_S, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_sGate(), statevec_sGateConj(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -3796,21 +3796,21 @@

    Author
    Tyson Jones
    -

    Definition at line 640 of file QuEST.c.

    -
    640  {
    -
    641  validateUniqueTargets(qureg, qb1, qb2, __func__);
    -
    642  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__); // uses 2qb unitary in QuEST_common
    -
    643 
    -
    644  statevec_sqrtSwapGate(qureg, qb1, qb2);
    -
    645  if (qureg.isDensityMatrix) {
    -
    646  int shift = qureg.numQubitsRepresented;
    -
    647  statevec_sqrtSwapGateConj(qureg, qb1+shift, qb2+shift);
    -
    648  }
    -
    649 
    -
    650  qasm_recordControlledGate(qureg, GATE_SQRT_SWAP, qb1, qb2);
    -
    651 }
    +

    Definition at line 639 of file QuEST.c.

    +
    639  {
    +
    640  validateUniqueTargets(qureg, qb1, qb2, __func__);
    +
    641  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__); // uses 2qb unitary in QuEST_common
    +
    642 
    +
    643  statevec_sqrtSwapGate(qureg, qb1, qb2);
    +
    644  if (qureg.isDensityMatrix) {
    +
    645  int shift = qureg.numQubitsRepresented;
    +
    646  statevec_sqrtSwapGateConj(qureg, qb1+shift, qb2+shift);
    +
    647  }
    +
    648 
    +
    649  qasm_recordControlledGate(qureg, GATE_SQRT_SWAP, qb1, qb2);
    +
    650 }
    -

    References GATE_SQRT_SWAP, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), validateMultiQubitMatrixFitsInNode(), and validateUniqueTargets().

    +

    References GATE_SQRT_SWAP, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), validateMultiQubitMatrixFitsInNode(), and validateUniqueTargets().

    Referenced by TEST_CASE().

    @@ -3880,20 +3880,20 @@

    Author
    Tyson Jones
    -

    Definition at line 628 of file QuEST.c.

    -
    628  {
    -
    629  validateUniqueTargets(qureg, qb1, qb2, __func__);
    -
    630 
    -
    631  statevec_swapQubitAmps(qureg, qb1, qb2);
    -
    632  if (qureg.isDensityMatrix) {
    -
    633  int shift = qureg.numQubitsRepresented;
    -
    634  statevec_swapQubitAmps(qureg, qb1+shift, qb2+shift);
    -
    635  }
    -
    636 
    -
    637  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
    -
    638 }
    +

    Definition at line 627 of file QuEST.c.

    +
    627  {
    +
    628  validateUniqueTargets(qureg, qb1, qb2, __func__);
    +
    629 
    +
    630  statevec_swapQubitAmps(qureg, qb1, qb2);
    +
    631  if (qureg.isDensityMatrix) {
    +
    632  int shift = qureg.numQubitsRepresented;
    +
    633  statevec_swapQubitAmps(qureg, qb1+shift, qb2+shift);
    +
    634  }
    +
    635 
    +
    636  qasm_recordControlledGate(qureg, GATE_SWAP, qb1, qb2);
    +
    637 }
    -

    References GATE_SWAP, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_swapQubitAmps(), and validateUniqueTargets().

    +

    References GATE_SWAP, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordControlledGate(), statevec_swapQubitAmps(), and validateUniqueTargets().

    Referenced by TEST_CASE().

    @@ -3956,19 +3956,19 @@

    Definition at line 477 of file QuEST.c.

    -
    477  {
    -
    478  validateTarget(qureg, targetQubit, __func__);
    -
    479 
    -
    480  statevec_tGate(qureg, targetQubit);
    -
    481  if (qureg.isDensityMatrix) {
    -
    482  statevec_tGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
    -
    483  }
    -
    484 
    -
    485  qasm_recordGate(qureg, GATE_T, targetQubit);
    -
    486 }
    +

    Definition at line 476 of file QuEST.c.

    +
    476  {
    +
    477  validateTarget(qureg, targetQubit, __func__);
    +
    478 
    +
    479  statevec_tGate(qureg, targetQubit);
    +
    480  if (qureg.isDensityMatrix) {
    +
    481  statevec_tGateConj(qureg, targetQubit+qureg.numQubitsRepresented);
    +
    482  }
    +
    483 
    +
    484  qasm_recordGate(qureg, GATE_T, targetQubit);
    +
    485 }
    -

    References GATE_T, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_tGate(), statevec_tGateConj(), and validateTarget().

    +

    References GATE_T, Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordGate(), statevec_tGate(), statevec_tGateConj(), and validateTarget().

    Referenced by TEST_CASE().

    @@ -4057,21 +4057,21 @@

    Author
    Tyson Jones
    -

    Definition at line 257 of file QuEST.c.

    -
    257  {
    -
    258  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
    -
    259  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    -
    260 
    -
    261  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
    -
    262  if (qureg.isDensityMatrix) {
    -
    263  int shift = qureg.numQubitsRepresented;
    -
    264  statevec_twoQubitUnitary(qureg, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    -
    265  }
    -
    266 
    -
    267  qasm_recordComment(qureg, "Here, an undisclosed 2-qubit unitary was applied.");
    -
    268 }
    +

    Definition at line 256 of file QuEST.c.

    +
    256  {
    +
    257  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
    +
    258  validateTwoQubitUnitaryMatrix(qureg, u, __func__);
    +
    259 
    +
    260  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
    +
    261  if (qureg.isDensityMatrix) {
    +
    262  int shift = qureg.numQubitsRepresented;
    +
    263  statevec_twoQubitUnitary(qureg, targetQubit1+shift, targetQubit2+shift, getConjugateMatrix4(u));
    +
    264  }
    +
    265 
    +
    266  qasm_recordComment(qureg, "Here, an undisclosed 2-qubit unitary was applied.");
    +
    267 }
    -

    References getConjugateMatrix4(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiTargets(), and validateTwoQubitUnitaryMatrix().

    +

    References getConjugateMatrix4(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiTargets(), and validateTwoQubitUnitaryMatrix().

    Referenced by TEST_CASE().

    @@ -4153,133 +4153,133 @@

    Definition at line 349 of file QuEST.c.

    -
    349  {
    -
    350  validateTarget(qureg, targetQubit, __func__);
    -
    351  validateOneQubitUnitaryMatrix(u, __func__);
    -
    352 
    -
    353  statevec_unitary(qureg, targetQubit, u);
    -
    354  if (qureg.isDensityMatrix) {
    -
    355  statevec_unitary(qureg, targetQubit+qureg.numQubitsRepresented, getConjugateMatrix2(u));
    -
    356  }
    -
    357 
    -
    358  qasm_recordUnitary(qureg, u, targetQubit);
    -
    359 }
    +

    Definition at line 348 of file QuEST.c.

    +
    348  {
    +
    349  validateTarget(qureg, targetQubit, __func__);
    +
    350  validateOneQubitUnitaryMatrix(u, __func__);
    +
    351 
    +
    352  statevec_unitary(qureg, targetQubit, u);
    +
    353  if (qureg.isDensityMatrix) {
    +
    354  statevec_unitary(qureg, targetQubit+qureg.numQubitsRepresented, getConjugateMatrix2(u));
    +
    355  }
    +
    356 
    +
    357  qasm_recordUnitary(qureg, u, targetQubit);
    +
    358 }
    -

    References getConjugateMatrix2(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordUnitary(), statevec_unitary(), validateOneQubitUnitaryMatrix(), and validateTarget().

    +

    References getConjugateMatrix2(), Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordUnitary(), statevec_unitary(), validateOneQubitUnitaryMatrix(), and validateTarget().

    Referenced by TEST_CASE().

    -
    void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Definition: QuEST_common.c:264
    -
    void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
    -
    void statevec_sGate(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:278
    -
    void statevec_pauliZ(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:271
    +
    void statevec_phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Definition: QuEST_common.c:254
    +
    void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
    +
    void statevec_sGate(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:268
    +
    void statevec_pauliZ(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:261
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:306
    -
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    -
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:257
    +
    void statevec_rotateX(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:296
    +
    void validateTarget(Qureg qureg, int targetQubit, const char *caller)
    +
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:256
    @ PAULI_Z
    Definition: QuEST.h:96
    -
    void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
    Definition: QuEST_common.c:463
    +
    void statevec_multiControlledMultiRotatePauli(Qureg qureg, long long int ctrlMask, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
    Definition: QuEST_common.c:453
    void qasm_recordParamGate(Qureg qureg, TargetGate gate, int targetQubit, qreal param)
    Definition: QuEST_qasm.c:187
    void shiftIndices(int *indices, int numIndices, int shift)
    Definition: QuEST_common.c:156
    -
    void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:577
    +
    void statevec_controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:567
    @ PAULI_I
    Definition: QuEST.h:96
    @ GATE_T
    Definition: QuEST_qasm.h:24
    @ GATE_PHASE_SHIFT
    Definition: QuEST_qasm.h:32
    void qasm_recordUnitary(Qureg qureg, ComplexMatrix2 u, int targetQubit)
    Definition: QuEST_qasm.c:208
    void qasm_recordMultiControlledGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit)
    Definition: QuEST_qasm.c:317
    -
    void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
    -
    void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:571
    -
    void statevec_tGateConj(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:299
    -
    void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    +
    void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
    +
    void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Definition: QuEST_common.c:561
    +
    void statevec_tGateConj(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:289
    +
    void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    ComplexMatrix4 getConjugateMatrix4(ComplexMatrix4 src)
    Definition: QuEST_common.c:110
    @ GATE_ROTATE_X
    Definition: QuEST_qasm.h:27
    -
    void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
    -
    void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    -
    void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
    Definition: QuEST_cpu.c:3277
    +
    void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
    +
    void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    +
    void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
    Definition: QuEST_cpu.c:3316
    void qasm_recordControlledCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int controlQubit, int targetQubit)
    Definition: QuEST_qasm.c:265
    @ GATE_ROTATE_Z
    Definition: QuEST_qasm.h:29
    @ GATE_SIGMA_Z
    Definition: QuEST_qasm.h:23
    -
    void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    +
    void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    Complex getConjugateScalar(Complex scalar)
    Definition: QuEST_common.c:91
    -
    void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Definition: QuEST_cpu.c:3187
    +
    void statevec_controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Definition: QuEST_cpu.c:3226
    @ GATE_HADAMARD
    Definition: QuEST_qasm.h:26
    ComplexMatrix2 getConjugateMatrix2(ComplexMatrix2 src)
    Definition: QuEST_common.c:105
    -
    void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Definition: QuEST_cpu.c:3227
    -
    void statevec_pauliY(Qureg qureg, int targetQubit)
    +
    void statevec_multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Definition: QuEST_cpu.c:3266
    +
    void statevec_pauliY(Qureg qureg, int targetQubit)
    void qasm_recordMultiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
    Definition: QuEST_qasm.c:382
    -
    void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:589
    -
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:686
    +
    void statevec_controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:579
    +
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:685
    void qasm_recordMultiStateControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int *controlState, int numControlQubits, int targetQubit)
    Definition: QuEST_qasm.c:363
    -
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:297
    -
    void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Definition: QuEST_common.c:397
    +
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:296
    +
    void statevec_sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Definition: QuEST_common.c:387
    @ PAULI_X
    Definition: QuEST.h:96
    -
    void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
    -
    void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
    -
    void validateVector(Vector vec, const char *caller)
    -
    void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
    -
    void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
    -
    void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    +
    void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
    +
    void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
    +
    void validateVector(Vector vec, const char *caller)
    +
    void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
    +
    void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
    +
    void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    void qasm_recordControlledGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit)
    Definition: QuEST_qasm.c:239
    -
    void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
    Definition: QuEST.c:706
    -
    void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
    +
    void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
    Definition: QuEST.c:705
    +
    void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
    void qasm_recordAxisRotation(Qureg qureg, qreal angle, Vector axis, int targetQubit)
    Definition: QuEST_qasm.c:224
    @ GATE_SQRT_SWAP
    Definition: QuEST_qasm.h:34
    -
    void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
    Definition: QuEST_cpu.c:3319
    +
    void statevec_multiControlledMultiRotateZ(Qureg qureg, long long int ctrlMask, long long int targMask, qreal angle)
    Definition: QuEST_cpu.c:3358
    @ GATE_SIGMA_X
    Definition: QuEST_qasm.h:21
    -
    void statevec_tGate(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:285
    -
    void validateControlState(int *controlState, int numControlQubits, const char *caller)
    -
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    +
    void statevec_tGate(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:275
    +
    void validateControlState(int *controlState, int numControlQubits, const char *caller)
    +
    void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
    void qasm_recordControlledParamGate(Qureg qureg, TargetGate gate, int controlQubit, int targetQubit, qreal param)
    Definition: QuEST_qasm.c:248
    -
    void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:324
    +
    void statevec_rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:314
    void setConjugateMatrixN(ComplexMatrixN m)
    Definition: QuEST_common.c:115
    -
    void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    +
    void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
    void qasm_recordControlledAxisRotation(Qureg qureg, qreal angle, Vector axis, int controlQubit, int targetQubit)
    Definition: QuEST_qasm.c:301
    long long int getQubitBitMask(int *qubits, int numQubits)
    Definition: QuEST_common.c:50
    -
    void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    +
    void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    @ PAULI_Y
    Definition: QuEST.h:96
    -
    void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
    applyConj=1 will apply conjugate operation, else applyConj=0
    Definition: QuEST_common.c:424
    -
    void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Definition: QuEST_cpu.c:3678
    +
    void statevec_multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle, int applyConj)
    applyConj=1 will apply conjugate operation, else applyConj=0
    Definition: QuEST_common.c:414
    +
    void statevec_multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Definition: QuEST_cpu.c:3718
    void qasm_recordComment(Qureg qureg, char *comment,...)
    Definition: QuEST_qasm.c:121
    -
    void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:583
    -
    void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:340
    -
    void statevec_sGateConj(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:292
    -
    void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:331
    +
    void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
    Definition: QuEST_common.c:573
    +
    void statevec_controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:330
    +
    void statevec_sGateConj(Qureg qureg, int targetQubit)
    Definition: QuEST_common.c:282
    +
    void statevec_rotateAroundAxisConj(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:321
    long long int getControlFlipMask(int *controlQubits, int *controlState, int numControlQubits)
    Definition: QuEST_common.c:60
    void qasm_recordMultiControlledUnitary(Qureg qureg, ComplexMatrix2 u, int *controlQubits, int numControlQubits, int targetQubit)
    additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
    Definition: QuEST_qasm.c:342
    void qasm_recordMultiControlledParamGate(Qureg qureg, TargetGate gate, int *controlQubits, int numControlQubits, int targetQubit, qreal param)
    Definition: QuEST_qasm.c:325
    -
    void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    -
    void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
    -
    void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:356
    +
    void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    +
    void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
    +
    void statevec_controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:346
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    -
    void statevec_hadamard(Qureg qureg, int targetQubit)
    -
    void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:312
    -
    void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
    -
    void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
    -
    void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
    Definition: QuEST_common.c:410
    -
    void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:368
    +
    void statevec_hadamard(Qureg qureg, int targetQubit)
    +
    void statevec_rotateY(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:302
    +
    void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
    +
    void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
    +
    void statevec_sqrtSwapGateConj(Qureg qureg, int qb1, int qb2)
    Definition: QuEST_common.c:400
    +
    void statevec_controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:358
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:327
    -
    void statevec_pauliX(Qureg qureg, int targetQubit)
    -
    void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
    +
    void statevec_pauliX(Qureg qureg, int targetQubit)
    +
    void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
    @ GATE_S
    Definition: QuEST_qasm.h:25
    @ GATE_SWAP
    Definition: QuEST_qasm.h:33
    -
    void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Definition: QuEST_cpu.c:3647
    +
    void statevec_controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Definition: QuEST_cpu.c:3687
    @ GATE_SIGMA_Y
    Definition: QuEST_qasm.h:22
    void qasm_recordCompactUnitary(Qureg qureg, Complex alpha, Complex beta, int targetQubit)
    Definition: QuEST_qasm.c:196
    void qasm_recordControlledUnitary(Qureg qureg, ComplexMatrix2 u, int controlQubit, int targetQubit)
    additionally performs Rz on target to restore the global phase lost from u in QASM U(a,...
    Definition: QuEST_qasm.c:279
    -
    void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:362
    -
    void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:347
    +
    void statevec_controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Definition: QuEST_common.c:352
    +
    void statevec_controlledRotateAroundAxisConj(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Definition: QuEST_common.c:337
    void qasm_recordGate(Qureg qureg, TargetGate gate, int targetQubit)
    Definition: QuEST_qasm.c:179
    -
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    -
    void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
    +
    void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
    +
    void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
    @ GATE_ROTATE_Y
    Definition: QuEST_qasm.h:28
    -
    void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:318
    -
    void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    -
    void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
    -
    void statevec_pauliYConj(Qureg qureg, int targetQubit)
    +
    void statevec_rotateZ(Qureg qureg, int rotQubit, qreal angle)
    Definition: QuEST_common.c:308
    +
    void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    +
    void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
    +
    void statevec_pauliYConj(Qureg qureg, int targetQubit)

    diff --git a/docs/group__unittest.html b/docs/group__unittest.html index 347afadda..098f8cb60 100644 --- a/docs/group__unittest.html +++ b/docs/group__unittest.html @@ -27,7 +27,7 @@ @@ -94,6 +94,8 @@    TEST_CASE ("applyPhaseFuncOverrides", "[operators]")   + TEST_CASE ("applyProjector", "[operators]") +   TEST_CASE ("applyQFT", "[operators]")    TEST_CASE ("applyTrotterCircuit", "[operators]") @@ -313,7 +315,7 @@

    Unit tests of the QuEST API, using Catch2 in C++14.

    Function Documentation

    -

    ◆ TEST_CASE() [1/123]

    +

    ◆ TEST_CASE() [1/124]

    @@ -388,12 +390,12 @@

    76  CLEANUP_TEST( quregVec, quregMatr );

    77 }
    -

    References applyDiagonalOp(), areEqual(), CLEANUP_TEST, createDiagonalOp(), destroyDiagonalOp(), getRandomReal(), DiagonalOp::imag, NUM_QUBITS, DiagonalOp::numElemsPerChunk, PREPARE_TEST, QUEST_ENV, DiagonalOp::real, syncDiagonalOp(), and toQMatrix().

    +

    References applyDiagonalOp(), areEqual(), CLEANUP_TEST, createDiagonalOp(), destroyDiagonalOp(), getRandomReal(), DiagonalOp::imag, NUM_QUBITS, DiagonalOp::numElemsPerChunk, PREPARE_TEST, QUEST_ENV, DiagonalOp::real, syncDiagonalOp(), and toQMatrix().

    -

    ◆ TEST_CASE() [2/123]

    +

    ◆ TEST_CASE() [2/124]

    @@ -535,12 +537,12 @@

    194  CLEANUP_TEST( quregVec, quregMatr );

    195 }
    -

    References applyFullQFT(), areEqual(), CLEANUP_TEST, getDFT(), getMixedDensityMatrix(), getPureDensityMatrix(), getRandomComplex(), getRandomOrthonormalVectors(), getRandomProbabilities(), getRandomQVector(), getRandomStateVector(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, and toQureg().

    +

    References applyFullQFT(), areEqual(), CLEANUP_TEST, getDFT(), getMixedDensityMatrix(), getPureDensityMatrix(), getRandomComplex(), getRandomOrthonormalVectors(), getRandomProbabilities(), getRandomQVector(), getRandomStateVector(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, and toQureg().

    -

    ◆ TEST_CASE() [3/123]

    +

    ◆ TEST_CASE() [3/124]

    @@ -612,12 +614,12 @@

    244  CLEANUP_TEST( quregVec, quregMatr );

    245 }
    -

    References applyMatrix2(), applyReferenceMatrix(), areEqual(), CLEANUP_TEST, getRandomQMatrix(), NUM_QUBITS, PREPARE_TEST, and toComplexMatrix2().

    +

    References applyMatrix2(), applyReferenceMatrix(), areEqual(), CLEANUP_TEST, getRandomQMatrix(), NUM_QUBITS, PREPARE_TEST, and toComplexMatrix2().

    -

    ◆ TEST_CASE() [4/123]

    +

    ◆ TEST_CASE() [4/124]

    @@ -704,12 +706,12 @@

    309  CLEANUP_TEST( quregVec, quregMatr );

    310 }
    -

    References applyMatrix4(), applyReferenceMatrix(), areEqual(), CLEANUP_TEST, getRandomQMatrix(), NUM_QUBITS, PREPARE_TEST, and toComplexMatrix4().

    +

    References applyMatrix4(), applyReferenceMatrix(), areEqual(), CLEANUP_TEST, getRandomQMatrix(), NUM_QUBITS, PREPARE_TEST, and toComplexMatrix4().

    -

    ◆ TEST_CASE() [5/123]

    +

    ◆ TEST_CASE() [5/124]

    @@ -842,12 +844,12 @@

    420  CLEANUP_TEST( quregVec, quregMatr );

    421 }
    -

    References applyMatrixN(), applyReferenceMatrix(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomQMatrix(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    +

    References applyMatrixN(), applyReferenceMatrix(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomQMatrix(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    -

    ◆ TEST_CASE() [6/123]

    +

    ◆ TEST_CASE() [6/124]

    @@ -1029,12 +1031,12 @@

    580  CLEANUP_TEST( quregVec, quregMatr );

    581 }
    -

    References applyMultiControlledMatrixN(), applyReferenceMatrix(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomQMatrix(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    +

    References applyMultiControlledMatrixN(), applyReferenceMatrix(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomQMatrix(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    -

    ◆ TEST_CASE() [7/123]

    +

    ◆ TEST_CASE() [7/124]

    @@ -1257,12 +1259,12 @@

    781  CLEANUP_TEST( quregVec, quregMatr );

    782 }
    -

    References applyMultiVarPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getKroneckerProduct(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NUM_QUBITS, PREPARE_TEST, qreal, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyMultiVarPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getKroneckerProduct(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NUM_QUBITS, PREPARE_TEST, qreal, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [8/123]

    +

    ◆ TEST_CASE() [8/124]

    @@ -1555,12 +1557,12 @@

    1052  CLEANUP_TEST( quregVec, quregMatr );

    1053 }
    -

    References applyMultiVarPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getKroneckerProduct(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NUM_QUBITS, PREPARE_TEST, qreal, setDiagMatrixOverrides(), sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyMultiVarPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getKroneckerProduct(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NUM_QUBITS, PREPARE_TEST, qreal, setDiagMatrixOverrides(), sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [9/123]

    +

    ◆ TEST_CASE() [9/124]

    @@ -1794,12 +1796,12 @@

    1264  CLEANUP_TEST( quregVec, quregMatr );

    1265 }
    -

    References applyNamedPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyNamedPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [10/123]

    +

    ◆ TEST_CASE() [10/124]

    @@ -2100,12 +2102,12 @@

    1543  CLEANUP_TEST( quregVec, quregMatr );

    1544 }
    -

    References applyNamedPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, setDiagMatrixOverrides(), sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyNamedPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, setDiagMatrixOverrides(), sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [11/123]

    +

    ◆ TEST_CASE() [11/124]

    @@ -2307,357 +2309,359 @@

    1723  qreal phase = 0;

    1724  for (int r=0; r<numRegs; r++)
    1725  phase += pow(regVals[i][r] - params[2+r], 2);
    -
    1726  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    1727  diagMatr[i][i] = expI(phase);
    -
    1728  }
    -
    1729 
    -
    1730  SECTION( "state-vector" ) {
    -
    1731 
    -
    1732  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1733  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1734  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1735  }
    -
    1736  SECTION( "density-matrix" ) {
    -
    1737 
    -
    1738  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1739  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1740  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1741  }
    -
    1742  }
    -
    1743  SECTION( "INVERSE_PRODUCT" ) {
    -
    1744 
    -
    1745  enum phaseFunc func = INVERSE_PRODUCT;
    -
    1746  qreal divPhase = getRandomReal(-4, 4);
    -
    1747 
    -
    1748  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1749  qreal phase = 1;
    -
    1750  for (int r=0; r<numRegs; r++)
    -
    1751  phase *= regVals[i][r];
    -
    1752  phase = (phase == 0.)? divPhase : 1. / phase;
    -
    1753  diagMatr[i][i] = expI(phase);
    -
    1754  }
    -
    1755 
    -
    1756  qreal params[] = {divPhase};
    -
    1757  int numParams = 1;
    -
    1758 
    -
    1759  SECTION( "state-vector" ) {
    -
    1760 
    -
    1761  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1762  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1763  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1764  }
    -
    1765  SECTION( "density-matrix" ) {
    -
    1766 
    -
    1767  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1768  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1769  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1770  }
    -
    1771  }
    -
    1772  SECTION( "SCALED_PRODUCT" ) {
    -
    1773 
    -
    1774  enum phaseFunc func = SCALED_PRODUCT;
    -
    1775  qreal coeff = getRandomReal(-10, 10);
    -
    1776 
    -
    1777  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1778  qreal phase = 1;
    -
    1779  for (int r=0; r<numRegs; r++)
    -
    1780  phase *= regVals[i][r];
    -
    1781  diagMatr[i][i] = expI(coeff * phase);
    -
    1782  }
    -
    1783 
    -
    1784  qreal params[] = {coeff};
    -
    1785  int numParams = 1;
    -
    1786 
    -
    1787  SECTION( "state-vector" ) {
    -
    1788 
    -
    1789  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1790  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1791  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1792  }
    -
    1793  SECTION( "density-matrix" ) {
    -
    1794 
    -
    1795  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1796  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1797  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1798  }
    -
    1799  }
    -
    1800  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    -
    1801 
    -
    1802  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    -
    1803  qreal coeff = getRandomReal(-10, 10);
    -
    1804  qreal divPhase = getRandomReal(-4, 4);
    -
    1805  qreal params[] = {coeff, divPhase};
    -
    1806  int numParams = 2;
    -
    1807 
    -
    1808  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1809  qreal phase = 1;
    -
    1810  for (int r=0; r<numRegs; r++)
    -
    1811  phase *= regVals[i][r];
    -
    1812  phase = (phase == 0)? divPhase : coeff / phase;
    -
    1813  diagMatr[i][i] = expI(phase);
    -
    1814  }
    -
    1815 
    -
    1816  SECTION( "state-vector" ) {
    -
    1817 
    -
    1818  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1819  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1820  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1821  }
    -
    1822  SECTION( "density-matrix" ) {
    -
    1823 
    -
    1824  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1825  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1826  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1827  }
    -
    1828  }
    -
    1829  SECTION( "INVERSE_DISTANCE" ) {
    -
    1830 
    -
    1831  enum phaseFunc func = INVERSE_DISTANCE;
    -
    1832  qreal divPhase = getRandomReal( -4, 4 );
    -
    1833  qreal params[] = {divPhase};
    -
    1834  int numParams = 1;
    -
    1835 
    -
    1836  // test only if there are an even number of registers
    -
    1837  if (numRegs%2 == 0) {
    -
    1838 
    -
    1839  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1840  qreal phase = 0;
    -
    1841  for (int r=0; r<numRegs; r+=2)
    -
    1842  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    1843  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    -
    1844  diagMatr[i][i] = expI(phase);
    -
    1845  }
    -
    1846  }
    -
    1847 
    -
    1848  SECTION( "state-vector" ) {
    -
    1849 
    -
    1850  if (numRegs%2 == 0) {
    -
    1851  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1852  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1853  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1854  }
    -
    1855  }
    -
    1856  SECTION( "density-matrix" ) {
    -
    1857 
    -
    1858  if (numRegs%2 == 0) {
    -
    1859  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1860  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1861  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1862  }
    -
    1863  }
    -
    1864  }
    -
    1865  SECTION( "SCALED_DISTANCE" ) {
    -
    1866 
    -
    1867  enum phaseFunc func = SCALED_DISTANCE;
    -
    1868  qreal coeff = getRandomReal( -10, 10 );
    -
    1869  qreal params[] = {coeff};
    -
    1870  int numParams = 1;
    -
    1871 
    -
    1872  // test only if there are an even number of registers
    -
    1873  if (numRegs%2 == 0) {
    -
    1874 
    -
    1875  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1876  qreal phase = 0;
    -
    1877  for (int r=0; r<numRegs; r+=2)
    -
    1878  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    1879  phase = coeff * sqrt(phase);
    -
    1880  diagMatr[i][i] = expI(phase);
    -
    1881  }
    -
    1882  }
    -
    1883 
    -
    1884  SECTION( "state-vector" ) {
    -
    1885 
    -
    1886  if (numRegs%2 == 0) {
    -
    1887  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1888  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1889  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1890  }
    -
    1891  }
    -
    1892  SECTION( "density-matrix" ) {
    -
    1893 
    -
    1894  if (numRegs%2 == 0) {
    -
    1895  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1896  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1897  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1898  }
    -
    1899  }
    -
    1900  }
    -
    1901  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    -
    1902 
    -
    1903  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    -
    1904  qreal coeff = getRandomReal( -10, 10 );
    -
    1905  qreal divPhase = getRandomReal( -4, 4 );
    -
    1906  qreal params[] = {coeff, divPhase};
    -
    1907  int numParams = 2;
    -
    1908 
    -
    1909  // test only if there are an even number of registers
    -
    1910  if (numRegs%2 == 0) {
    -
    1911 
    -
    1912  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1913  qreal phase = 0;
    -
    1914  for (int r=0; r<numRegs; r+=2)
    -
    1915  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    1916  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    -
    1917  diagMatr[i][i] = expI(phase);
    -
    1918  }
    -
    1919  }
    -
    1920 
    -
    1921  SECTION( "state-vector" ) {
    -
    1922 
    -
    1923  if (numRegs%2 == 0) {
    -
    1924  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1925  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1926  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1927  }
    -
    1928  }
    -
    1929  SECTION( "density-matrix" ) {
    -
    1930 
    -
    1931  if (numRegs%2 == 0) {
    -
    1932  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1933  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1934  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1935  }
    -
    1936  }
    -
    1937  }
    -
    1938  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    -
    1939 
    - -
    1941  int numParams = 2 + numRegs/2;
    -
    1942  qreal params[numParams];
    -
    1943 
    -
    1944  // test only if there are an even number of registers
    -
    1945  if (numRegs%2 == 0) {
    -
    1946 
    -
    1947  params[0] = getRandomReal( -10, 10 ); // scaling
    -
    1948  params[1] = getRandomReal( -4, 4 ); // divergence override
    -
    1949  for (int r=0; r<numRegs/2; r++)
    -
    1950  params[2+r] = getRandomReal( -8, 8 ); // shifts
    -
    1951 
    -
    1952  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1953  qreal phase = 0;
    -
    1954  for (int r=0; r<numRegs; r+=2)
    -
    1955  phase += pow(regVals[i][r+1]-regVals[i][r]-params[2+r/2], 2);
    -
    1956  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    1957  diagMatr[i][i] = expI(phase);
    -
    1958  }
    -
    1959  }
    -
    1960 
    -
    1961  SECTION( "state-vector" ) {
    -
    1962 
    -
    1963  if (numRegs%2 == 0) {
    -
    1964  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1965  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1966  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1967  }
    -
    1968  }
    -
    1969  SECTION( "density-matrix" ) {
    -
    1970 
    -
    1971  if (numRegs%2 == 0) {
    -
    1972  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1973  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1974  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1975  }
    -
    1976  }
    -
    1977  }
    -
    1978  }
    -
    1979  SECTION( "input validation" ) {
    -
    1980 
    -
    1981  int numRegs = 2;
    -
    1982  int numQubitsPerReg[] = {2,3};
    -
    1983  int regs[] = {0,1,2,3,4};
    -
    1984 
    -
    1985  SECTION( "number of registers" ) {
    -
    1986 
    -
    1987  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    -
    1988  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubit subregisters") );
    -
    1989  }
    -
    1990  SECTION( "number of qubits" ) {
    -
    1991 
    -
    1992  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    -
    1993  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubits") );
    -
    1994  }
    -
    1995  SECTION( "repetition of qubits" ) {
    -
    1996 
    -
    1997  regs[GENERATE(2,3,4)] = regs[1];
    -
    1998  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("The qubits must be unique") );
    -
    1999  }
    -
    2000  SECTION( "qubit indices" ) {
    -
    2001 
    -
    2002  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    -
    2003  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid qubit index") );
    -
    2004  }
    -
    2005  SECTION( "bit encoding name" ) {
    -
    2006 
    -
    2007  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    -
    2008  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0), Contains("Invalid bit encoding") );
    -
    2009  }
    -
    2010  SECTION( "two's complement register" ) {
    -
    2011 
    -
    2012  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    -
    2013  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    -
    2014  }
    -
    2015  SECTION( "phase function name" ) {
    -
    2016 
    -
    2017  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    -
    2018  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0), Contains("Invalid named phase function") );
    -
    2019  }
    -
    2020  SECTION( "phase function parameters" ) {
    -
    2021 
    -
    2022  qreal params[numRegs + 3];
    -
    2023  for (int r=0; r<numRegs + 3; r++)
    -
    2024  params[r] = 0;
    -
    2025 
    -
    2026  SECTION( "no parameter functions" ) {
    -
    2027 
    -
    2028  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    -
    2029  int numParams = GENERATE( -1, 1, 2 );
    -
    2030  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2031  }
    -
    2032  SECTION( "single parameter functions" ) {
    -
    2033 
    - -
    2035  int numParams = GENERATE( -1, 0, 2 );
    -
    2036  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2037  }
    -
    2038  SECTION( "two parameter functions" ) {
    -
    2039 
    - -
    2041  int numParams = GENERATE( 0, 1, 3 );
    -
    2042  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2043  }
    -
    2044  SECTION( "shifted distance" ) {
    -
    2045 
    -
    2046  if (numRegs%2 == 0) {
    - -
    2048  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    -
    2049  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2050  }
    -
    2051  }
    -
    2052  SECTION( "shifted norm" ) {
    -
    2053 
    - -
    2055  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    -
    2056  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2057  }
    -
    2058  }
    -
    2059  SECTION( "distance pair registers" ) {
    -
    2060 
    -
    2061  int numQb[] = {1,1,1,1,1};
    -
    2062  int qb[] = {0,1,2,3,4};
    -
    2063 
    -
    2064  numRegs = GENERATE( 1, 3, 5 );
    -
    2065  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    -
    2066  }
    -
    2067  }
    -
    2068  CLEANUP_TEST( quregVec, quregMatr );
    -
    2069 }
    +
    1726  phase = sqrt(phase);
    +
    1727  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    1728  diagMatr[i][i] = expI(phase);
    +
    1729  }
    +
    1730 
    +
    1731  SECTION( "state-vector" ) {
    +
    1732 
    +
    1733  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1734  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1735  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1736  }
    +
    1737  SECTION( "density-matrix" ) {
    +
    1738 
    +
    1739  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1740  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1741  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1742  }
    +
    1743  }
    +
    1744  SECTION( "INVERSE_PRODUCT" ) {
    +
    1745 
    +
    1746  enum phaseFunc func = INVERSE_PRODUCT;
    +
    1747  qreal divPhase = getRandomReal(-4, 4);
    +
    1748 
    +
    1749  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1750  qreal phase = 1;
    +
    1751  for (int r=0; r<numRegs; r++)
    +
    1752  phase *= regVals[i][r];
    +
    1753  phase = (phase == 0.)? divPhase : 1. / phase;
    +
    1754  diagMatr[i][i] = expI(phase);
    +
    1755  }
    +
    1756 
    +
    1757  qreal params[] = {divPhase};
    +
    1758  int numParams = 1;
    +
    1759 
    +
    1760  SECTION( "state-vector" ) {
    +
    1761 
    +
    1762  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1763  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1764  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1765  }
    +
    1766  SECTION( "density-matrix" ) {
    +
    1767 
    +
    1768  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1769  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1770  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1771  }
    +
    1772  }
    +
    1773  SECTION( "SCALED_PRODUCT" ) {
    +
    1774 
    +
    1775  enum phaseFunc func = SCALED_PRODUCT;
    +
    1776  qreal coeff = getRandomReal(-10, 10);
    +
    1777 
    +
    1778  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1779  qreal phase = 1;
    +
    1780  for (int r=0; r<numRegs; r++)
    +
    1781  phase *= regVals[i][r];
    +
    1782  diagMatr[i][i] = expI(coeff * phase);
    +
    1783  }
    +
    1784 
    +
    1785  qreal params[] = {coeff};
    +
    1786  int numParams = 1;
    +
    1787 
    +
    1788  SECTION( "state-vector" ) {
    +
    1789 
    +
    1790  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1791  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1792  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1793  }
    +
    1794  SECTION( "density-matrix" ) {
    +
    1795 
    +
    1796  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1797  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1798  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1799  }
    +
    1800  }
    +
    1801  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    +
    1802 
    +
    1803  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    +
    1804  qreal coeff = getRandomReal(-10, 10);
    +
    1805  qreal divPhase = getRandomReal(-4, 4);
    +
    1806  qreal params[] = {coeff, divPhase};
    +
    1807  int numParams = 2;
    +
    1808 
    +
    1809  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1810  qreal phase = 1;
    +
    1811  for (int r=0; r<numRegs; r++)
    +
    1812  phase *= regVals[i][r];
    +
    1813  phase = (phase == 0)? divPhase : coeff / phase;
    +
    1814  diagMatr[i][i] = expI(phase);
    +
    1815  }
    +
    1816 
    +
    1817  SECTION( "state-vector" ) {
    +
    1818 
    +
    1819  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1820  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1821  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1822  }
    +
    1823  SECTION( "density-matrix" ) {
    +
    1824 
    +
    1825  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1826  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1827  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1828  }
    +
    1829  }
    +
    1830  SECTION( "INVERSE_DISTANCE" ) {
    +
    1831 
    +
    1832  enum phaseFunc func = INVERSE_DISTANCE;
    +
    1833  qreal divPhase = getRandomReal( -4, 4 );
    +
    1834  qreal params[] = {divPhase};
    +
    1835  int numParams = 1;
    +
    1836 
    +
    1837  // test only if there are an even number of registers
    +
    1838  if (numRegs%2 == 0) {
    +
    1839 
    +
    1840  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1841  qreal phase = 0;
    +
    1842  for (int r=0; r<numRegs; r+=2)
    +
    1843  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    1844  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    +
    1845  diagMatr[i][i] = expI(phase);
    +
    1846  }
    +
    1847  }
    +
    1848 
    +
    1849  SECTION( "state-vector" ) {
    +
    1850 
    +
    1851  if (numRegs%2 == 0) {
    +
    1852  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1853  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1854  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1855  }
    +
    1856  }
    +
    1857  SECTION( "density-matrix" ) {
    +
    1858 
    +
    1859  if (numRegs%2 == 0) {
    +
    1860  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1861  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1862  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1863  }
    +
    1864  }
    +
    1865  }
    +
    1866  SECTION( "SCALED_DISTANCE" ) {
    +
    1867 
    +
    1868  enum phaseFunc func = SCALED_DISTANCE;
    +
    1869  qreal coeff = getRandomReal( -10, 10 );
    +
    1870  qreal params[] = {coeff};
    +
    1871  int numParams = 1;
    +
    1872 
    +
    1873  // test only if there are an even number of registers
    +
    1874  if (numRegs%2 == 0) {
    +
    1875 
    +
    1876  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1877  qreal phase = 0;
    +
    1878  for (int r=0; r<numRegs; r+=2)
    +
    1879  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    1880  phase = coeff * sqrt(phase);
    +
    1881  diagMatr[i][i] = expI(phase);
    +
    1882  }
    +
    1883  }
    +
    1884 
    +
    1885  SECTION( "state-vector" ) {
    +
    1886 
    +
    1887  if (numRegs%2 == 0) {
    +
    1888  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1889  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1890  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1891  }
    +
    1892  }
    +
    1893  SECTION( "density-matrix" ) {
    +
    1894 
    +
    1895  if (numRegs%2 == 0) {
    +
    1896  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1897  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1898  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1899  }
    +
    1900  }
    +
    1901  }
    +
    1902  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    +
    1903 
    +
    1904  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    +
    1905  qreal coeff = getRandomReal( -10, 10 );
    +
    1906  qreal divPhase = getRandomReal( -4, 4 );
    +
    1907  qreal params[] = {coeff, divPhase};
    +
    1908  int numParams = 2;
    +
    1909 
    +
    1910  // test only if there are an even number of registers
    +
    1911  if (numRegs%2 == 0) {
    +
    1912 
    +
    1913  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1914  qreal phase = 0;
    +
    1915  for (int r=0; r<numRegs; r+=2)
    +
    1916  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    1917  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    +
    1918  diagMatr[i][i] = expI(phase);
    +
    1919  }
    +
    1920  }
    +
    1921 
    +
    1922  SECTION( "state-vector" ) {
    +
    1923 
    +
    1924  if (numRegs%2 == 0) {
    +
    1925  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1926  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1927  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1928  }
    +
    1929  }
    +
    1930  SECTION( "density-matrix" ) {
    +
    1931 
    +
    1932  if (numRegs%2 == 0) {
    +
    1933  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1934  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1935  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1936  }
    +
    1937  }
    +
    1938  }
    +
    1939  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    +
    1940 
    + +
    1942  int numParams = 2 + numRegs/2;
    +
    1943  qreal params[numParams];
    +
    1944 
    +
    1945  // test only if there are an even number of registers
    +
    1946  if (numRegs%2 == 0) {
    +
    1947 
    +
    1948  params[0] = getRandomReal( -10, 10 ); // scaling
    +
    1949  params[1] = getRandomReal( -4, 4 ); // divergence override
    +
    1950  for (int r=0; r<numRegs/2; r++)
    +
    1951  params[2+r] = getRandomReal( -8, 8 ); // shifts
    +
    1952 
    +
    1953  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1954  qreal phase = 0;
    +
    1955  for (int r=0; r<numRegs; r+=2)
    +
    1956  phase += pow(regVals[i][r]-regVals[i][r+1]-params[2+r/2], 2);
    +
    1957  phase = sqrt(phase);
    +
    1958  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    1959  diagMatr[i][i] = expI(phase);
    +
    1960  }
    +
    1961  }
    +
    1962 
    +
    1963  SECTION( "state-vector" ) {
    +
    1964 
    +
    1965  if (numRegs%2 == 0) {
    +
    1966  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1967  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1968  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1969  }
    +
    1970  }
    +
    1971  SECTION( "density-matrix" ) {
    +
    1972 
    +
    1973  if (numRegs%2 == 0) {
    +
    1974  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1975  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1976  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1977  }
    +
    1978  }
    +
    1979  }
    +
    1980  }
    +
    1981  SECTION( "input validation" ) {
    +
    1982 
    +
    1983  int numRegs = 2;
    +
    1984  int numQubitsPerReg[] = {2,3};
    +
    1985  int regs[] = {0,1,2,3,4};
    +
    1986 
    +
    1987  SECTION( "number of registers" ) {
    +
    1988 
    +
    1989  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    +
    1990  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubit subregisters") );
    +
    1991  }
    +
    1992  SECTION( "number of qubits" ) {
    +
    1993 
    +
    1994  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    +
    1995  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubits") );
    +
    1996  }
    +
    1997  SECTION( "repetition of qubits" ) {
    +
    1998 
    +
    1999  regs[GENERATE(2,3,4)] = regs[1];
    +
    2000  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("The qubits must be unique") );
    +
    2001  }
    +
    2002  SECTION( "qubit indices" ) {
    +
    2003 
    +
    2004  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    +
    2005  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid qubit index") );
    +
    2006  }
    +
    2007  SECTION( "bit encoding name" ) {
    +
    2008 
    +
    2009  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    +
    2010  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0), Contains("Invalid bit encoding") );
    +
    2011  }
    +
    2012  SECTION( "two's complement register" ) {
    +
    2013 
    +
    2014  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    +
    2015  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    +
    2016  }
    +
    2017  SECTION( "phase function name" ) {
    +
    2018 
    +
    2019  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    +
    2020  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0), Contains("Invalid named phase function") );
    +
    2021  }
    +
    2022  SECTION( "phase function parameters" ) {
    +
    2023 
    +
    2024  qreal params[numRegs + 3];
    +
    2025  for (int r=0; r<numRegs + 3; r++)
    +
    2026  params[r] = 0;
    +
    2027 
    +
    2028  SECTION( "no parameter functions" ) {
    +
    2029 
    +
    2030  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    +
    2031  int numParams = GENERATE( -1, 1, 2 );
    +
    2032  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2033  }
    +
    2034  SECTION( "single parameter functions" ) {
    +
    2035 
    + +
    2037  int numParams = GENERATE( -1, 0, 2 );
    +
    2038  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2039  }
    +
    2040  SECTION( "two parameter functions" ) {
    +
    2041 
    + +
    2043  int numParams = GENERATE( 0, 1, 3 );
    +
    2044  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2045  }
    +
    2046  SECTION( "shifted distance" ) {
    +
    2047 
    +
    2048  if (numRegs%2 == 0) {
    + +
    2050  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    +
    2051  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2052  }
    +
    2053  }
    +
    2054  SECTION( "shifted norm" ) {
    +
    2055 
    + +
    2057  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    +
    2058  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2059  }
    +
    2060  }
    +
    2061  SECTION( "distance pair registers" ) {
    +
    2062 
    +
    2063  int numQb[] = {1,1,1,1,1};
    +
    2064  int qb[] = {0,1,2,3,4};
    +
    2065 
    +
    2066  numRegs = GENERATE( 1, 3, 5 );
    +
    2067  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    +
    2068  }
    +
    2069  }
    +
    2070  CLEANUP_TEST( quregVec, quregMatr );
    +
    2071 }
    -

    References applyParamNamedPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyParamNamedPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [12/123]

    +

    ◆ TEST_CASE() [12/124]

    @@ -2684,601 +2688,603 @@

    See also
    applyParamNamedPhaseFuncOverrides
    Author
    Tyson Jones
    -

    Definition at line 2077 of file test_operators.cpp.

    -
    2077  {
    -
    2078 
    -
    2079  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2080 
    -
    2081  SECTION( "correctness" ) {
    -
    2082 
    -
    2083  // try every kind of binary encoding
    -
    2084  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    -
    2085 
    -
    2086  // try every possible number of registers
    -
    2087  // (between #qubits containing 1, and 1 containing #qubits)
    -
    2088  int numRegs;
    -
    2089  int maxNumRegs = 0;
    -
    2090  if (encoding == UNSIGNED)
    -
    2091  maxNumRegs = NUM_QUBITS;
    -
    2092  if (encoding == TWOS_COMPLEMENT)
    -
    2093  maxNumRegs = NUM_QUBITS/2; // floors
    -
    2094  numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
    -
    2095 
    -
    2096  // try every possible total number of involved qubits
    -
    2097  int totalNumQubits;
    -
    2098  int minTotalQubits = 0;
    -
    2099  if (encoding == UNSIGNED)
    -
    2100  // each register must contain at least 1 qubit
    -
    2101  minTotalQubits = numRegs;
    -
    2102  if (encoding == TWOS_COMPLEMENT)
    -
    2103  // each register must contain at least 2 qubits
    -
    2104  minTotalQubits = 2*numRegs;
    -
    2105  totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
    -
    2106 
    -
    2107  // try every qubits subset and ordering
    -
    2108  int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
    -
    2109 
    -
    2110  // assign each sub-reg its minimum length
    -
    2111  int unallocQubits = totalNumQubits;
    -
    2112  int numQubitsPerReg[numRegs];
    -
    2113  for (int i=0; i<numRegs; i++)
    -
    2114  if (encoding == UNSIGNED) {
    -
    2115  numQubitsPerReg[i] = 1;
    -
    2116  unallocQubits -= 1;
    -
    2117  }
    -
    2118  else if (encoding == TWOS_COMPLEMENT) {
    -
    2119  numQubitsPerReg[i] = 2;
    -
    2120  unallocQubits -= 2;
    -
    2121  }
    -
    2122  // and randomly allocate the remaining qubits between the registers
    -
    2123  while (unallocQubits > 0) {
    -
    2124  numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
    -
    2125  unallocQubits--;
    -
    2126  }
    -
    2127 
    -
    2128 
    -
    2129  // choose a random number of overrides (even overriding every amplitude)
    -
    2130  int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
    -
    2131 
    -
    2132  // randomise each override index (uniqueness isn't checked)
    -
    2133  long long int overrideInds[numOverrides*numRegs];
    -
    2134  int flatInd = 0;
    -
    2135  for (int v=0; v<numOverrides; v++) {
    -
    2136  for (int r=0; r<numRegs; r++) {
    -
    2137  if (encoding == UNSIGNED)
    -
    2138  overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
    -
    2139  else if (encoding == TWOS_COMPLEMENT)
    -
    2140  overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
    -
    2141  flatInd++;
    -
    2142  }
    -
    2143  }
    -
    2144 
    -
    2145  // override to a random phase
    -
    2146  qreal overridePhases[numOverrides];
    -
    2147  for (int v=0; v<numOverrides; v++)
    -
    2148  overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    -
    2149 
    -
    2150 
    -
    2151  // determine the values corresponding to each register for all basis states
    -
    2152  qreal regVals[1<<totalNumQubits][numRegs];
    -
    2153  for (long long int i=0; i<(1<<totalNumQubits); i++) {
    -
    2154 
    -
    2155  long long int bits = i;
    -
    2156  for (int r=0; r<numRegs; r++) {
    -
    2157  regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
    -
    2158  bits = bits >> numQubitsPerReg[r];
    -
    2159 
    -
    2160  if (encoding == TWOS_COMPLEMENT)
    -
    2161  regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
    -
    2162  }
    -
    2163  }
    -
    2164 
    -
    2165  /* produce a reference diagonal matrix which assumes the qubits are
    -
    2166  * contiguous and strictly increasing between the registers, and hence
    -
    2167  * only depends on the number of qubits in each register.
    -
    2168  */
    -
    2169  QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
    -
    2170 
    -
    2171 
    -
    2172  SECTION( "INVERSE_NORM" ) {
    -
    2173 
    -
    2174  enum phaseFunc func = INVERSE_NORM;
    -
    2175  qreal divPhase = getRandomReal(-4, 4);
    -
    2176  qreal params[] = {divPhase};
    -
    2177  int numParams = 1;
    -
    2178 
    -
    2179  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2180  qreal phase = 0;
    -
    2181  for (int r=0; r<numRegs; r++)
    -
    2182  phase += pow(regVals[i][r], 2);
    -
    2183  phase = (phase == 0.)? divPhase : 1/sqrt(phase);
    -
    2184  diagMatr[i][i] = expI(phase);
    -
    2185  }
    -
    2186  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2187 
    -
    2188  SECTION( "state-vector" ) {
    -
    2189 
    -
    2190  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2191  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2192  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2193  }
    -
    2194  SECTION( "density-matrix" ) {
    -
    2195 
    -
    2196  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2197  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2198  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2199  }
    -
    2200  }
    -
    2201  SECTION( "SCALED_NORM" ) {
    -
    2202 
    -
    2203  enum phaseFunc func = SCALED_NORM;
    -
    2204  qreal coeff = getRandomReal(-10, 10);
    -
    2205  qreal params[] = {coeff};
    -
    2206  int numParams = 1;
    -
    2207 
    -
    2208  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2209  qreal phase = 0;
    -
    2210  for (int r=0; r<numRegs; r++)
    -
    2211  phase += pow(regVals[i][r], 2);
    -
    2212  phase = coeff * sqrt(phase);
    -
    2213  diagMatr[i][i] = expI(phase);
    -
    2214  }
    -
    2215  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2216 
    -
    2217  SECTION( "state-vector" ) {
    -
    2218 
    -
    2219  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2220  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2221  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2222  }
    -
    2223  SECTION( "density-matrix" ) {
    -
    2224 
    -
    2225  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2226  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2227  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2228  }
    -
    2229  }
    -
    2230  SECTION( "SCALED_INVERSE_NORM" ) {
    -
    2231 
    -
    2232  enum phaseFunc func = SCALED_INVERSE_NORM;
    -
    2233  qreal coeff = getRandomReal(-10, 10);
    -
    2234  qreal divPhase = getRandomReal(-4, 4);
    -
    2235  qreal params[] = {coeff, divPhase};
    -
    2236  int numParams = 2;
    -
    2237 
    -
    2238  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2239  qreal phase = 0;
    -
    2240  for (int r=0; r<numRegs; r++)
    -
    2241  phase += pow(regVals[i][r], 2);
    -
    2242  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    -
    2243  diagMatr[i][i] = expI(phase);
    -
    2244  }
    -
    2245  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2246 
    -
    2247  SECTION( "state-vector" ) {
    -
    2248 
    -
    2249  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2250  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2251  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2252  }
    -
    2253  SECTION( "density-matrix" ) {
    -
    2254 
    -
    2255  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2256  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2257  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2258  }
    -
    2259  }
    -
    2260  SECTION( "SCALED_INVERSE_SHIFTED_NORM" ) {
    -
    2261 
    - -
    2263  int numParams = 2 + numRegs;
    -
    2264  qreal params[numParams];
    -
    2265  params[0] = getRandomReal(-10, 10); // scaling
    -
    2266  params[1] = getRandomReal(-4, 4); // divergence override
    -
    2267  for (int r=0; r<numRegs; r++)
    -
    2268  params[2+r] = getRandomReal(-8, 8); // shifts
    -
    2269 
    -
    2270  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2271  qreal phase = 0;
    -
    2272  for (int r=0; r<numRegs; r++)
    -
    2273  phase += pow(regVals[i][r] - params[2+r], 2);
    -
    2274  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    2275  diagMatr[i][i] = expI(phase);
    -
    2276  }
    -
    2277  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2278 
    -
    2279  SECTION( "state-vector" ) {
    -
    2280 
    -
    2281  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2282  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2283  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2284  }
    -
    2285  SECTION( "density-matrix" ) {
    -
    2286 
    -
    2287  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2288  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2289  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2290  }
    -
    2291  }
    -
    2292  SECTION( "INVERSE_PRODUCT" ) {
    -
    2293 
    -
    2294  enum phaseFunc func = INVERSE_PRODUCT;
    -
    2295  qreal divPhase = getRandomReal(-4, 4);
    -
    2296  qreal params[] = {divPhase};
    -
    2297  int numParams = 1;
    -
    2298 
    -
    2299  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2300  qreal phase = 1;
    -
    2301  for (int r=0; r<numRegs; r++)
    -
    2302  phase *= regVals[i][r];
    -
    2303  phase = (phase == 0.)? divPhase : 1. / phase;
    -
    2304  diagMatr[i][i] = expI(phase);
    -
    2305  }
    -
    2306  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2307 
    -
    2308  SECTION( "state-vector" ) {
    -
    2309 
    -
    2310  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2311  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2312  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2313  }
    -
    2314  SECTION( "density-matrix" ) {
    -
    2315 
    -
    2316  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2317  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2318  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2319  }
    -
    2320  }
    -
    2321  SECTION( "SCALED_PRODUCT" ) {
    -
    2322 
    -
    2323  enum phaseFunc func = SCALED_PRODUCT;
    -
    2324  qreal coeff = getRandomReal(-10, 10);
    -
    2325  qreal params[] = {coeff};
    -
    2326  int numParams = 1;
    -
    2327 
    -
    2328  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2329  qreal phase = 1;
    -
    2330  for (int r=0; r<numRegs; r++)
    -
    2331  phase *= regVals[i][r];
    -
    2332  diagMatr[i][i] = expI(coeff * phase);
    -
    2333  }
    -
    2334  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2335 
    -
    2336  SECTION( "state-vector" ) {
    -
    2337 
    -
    2338  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2339  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2340  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2341  }
    -
    2342  SECTION( "density-matrix" ) {
    -
    2343 
    -
    2344  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2345  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2346  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2347  }
    -
    2348  }
    -
    2349  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    -
    2350 
    -
    2351  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    -
    2352  qreal coeff = getRandomReal(-10, 10);
    -
    2353  qreal divPhase = getRandomReal(-4, 4);
    -
    2354  qreal params[] = {coeff, divPhase};
    -
    2355  int numParams = 2;
    -
    2356 
    -
    2357  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2358  qreal phase = 1;
    -
    2359  for (int r=0; r<numRegs; r++)
    -
    2360  phase *= regVals[i][r];
    -
    2361  phase = (phase == 0)? divPhase : coeff / phase;
    -
    2362  diagMatr[i][i] = expI(phase);
    -
    2363  }
    -
    2364  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2365 
    -
    2366  SECTION( "state-vector" ) {
    -
    2367 
    -
    2368  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2369  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2370  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2371  }
    -
    2372  SECTION( "density-matrix" ) {
    -
    2373 
    -
    2374  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2375  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2376  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2377  }
    -
    2378  }
    -
    2379  SECTION( "INVERSE_DISTANCE" ) {
    -
    2380 
    -
    2381  enum phaseFunc func = INVERSE_DISTANCE;
    -
    2382  qreal divPhase = getRandomReal( -4, 4 );
    -
    2383  qreal params[] = {divPhase};
    -
    2384  int numParams = 1;
    -
    2385 
    -
    2386  // test only if there are an even number of registers
    -
    2387  if (numRegs%2 == 0) {
    -
    2388 
    -
    2389  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2390  qreal phase = 0;
    -
    2391  for (int r=0; r<numRegs; r+=2)
    -
    2392  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    2393  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    -
    2394  diagMatr[i][i] = expI(phase);
    -
    2395  }
    -
    2396  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2397  }
    -
    2398 
    -
    2399  SECTION( "state-vector" ) {
    -
    2400 
    -
    2401  if (numRegs%2 == 0) {
    -
    2402  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2403  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2404  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2405  }
    -
    2406  }
    -
    2407  SECTION( "density-matrix" ) {
    -
    2408 
    -
    2409  if (numRegs%2 == 0) {
    -
    2410  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2411  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2412  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2413  }
    -
    2414  }
    -
    2415  }
    -
    2416  SECTION( "SCALED_DISTANCE" ) {
    -
    2417 
    -
    2418  enum phaseFunc func = SCALED_DISTANCE;
    -
    2419  qreal coeff = getRandomReal( -10, 10 );
    -
    2420  qreal params[] = {coeff};
    -
    2421  int numParams = 1;
    -
    2422 
    -
    2423  // test only if there are an even number of registers
    -
    2424  if (numRegs%2 == 0) {
    -
    2425 
    -
    2426  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2427  qreal phase = 0;
    -
    2428  for (int r=0; r<numRegs; r+=2)
    -
    2429  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    2430  phase = coeff * sqrt(phase);
    -
    2431  diagMatr[i][i] = expI(phase);
    -
    2432  }
    -
    2433  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2434  }
    -
    2435 
    -
    2436  SECTION( "state-vector" ) {
    -
    2437 
    -
    2438  if (numRegs%2 == 0) {
    -
    2439  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2440  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2441  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2442  }
    -
    2443  }
    -
    2444  SECTION( "density-matrix" ) {
    -
    2445 
    -
    2446  if (numRegs%2 == 0) {
    -
    2447  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2448  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2449  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2450  }
    -
    2451  }
    -
    2452  }
    -
    2453  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    -
    2454 
    -
    2455  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    -
    2456  qreal coeff = getRandomReal( -10, 10 );
    -
    2457  qreal divPhase = getRandomReal( -4, 4 );
    -
    2458  qreal params[] = {coeff, divPhase};
    -
    2459  int numParams = 2;
    -
    2460 
    -
    2461  // test only if there are an even number of registers
    -
    2462  if (numRegs%2 == 0) {
    -
    2463 
    -
    2464  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2465  qreal phase = 0;
    -
    2466  for (int r=0; r<numRegs; r+=2)
    -
    2467  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    2468  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    -
    2469  diagMatr[i][i] = expI(phase);
    -
    2470  }
    -
    2471  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2472  }
    -
    2473 
    -
    2474  SECTION( "state-vector" ) {
    -
    2475 
    -
    2476  if (numRegs%2 == 0) {
    -
    2477  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2478  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2479  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2480  }
    -
    2481  }
    -
    2482  SECTION( "density-matrix" ) {
    -
    2483 
    -
    2484  if (numRegs%2 == 0) {
    -
    2485  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2486  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2487  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2488  }
    -
    2489  }
    -
    2490  }
    -
    2491  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    -
    2492 
    - -
    2494  int numParams = 2 + numRegs/2;
    -
    2495  qreal params[numParams];
    -
    2496 
    -
    2497  // test only if there are an even number of registers
    -
    2498  if (numRegs%2 == 0) {
    -
    2499 
    -
    2500  params[0] = getRandomReal( -10, 10 ); // scaling
    -
    2501  params[1] = getRandomReal( -4, 4 ); // divergence override
    -
    2502  for (int r=0; r<numRegs/2; r++)
    -
    2503  params[2+r] = getRandomReal( -8, 8 ); // shifts
    -
    2504 
    -
    2505  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2506  qreal phase = 0;
    -
    2507  for (int r=0; r<numRegs; r+=2)
    -
    2508  phase += pow(regVals[i][r+1]-regVals[i][r]-params[2+r/2], 2);
    -
    2509  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    2510  diagMatr[i][i] = expI(phase);
    -
    2511  }
    -
    2512 
    -
    2513  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2514  }
    -
    2515 
    -
    2516  SECTION( "state-vector" ) {
    -
    2517 
    -
    2518  if (numRegs%2 == 0) {
    -
    2519  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2520  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2521  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2522  }
    -
    2523  }
    -
    2524  SECTION( "density-matrix" ) {
    -
    2525 
    -
    2526  if (numRegs%2 == 0) {
    -
    2527  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2528  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2529  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2530  }
    -
    2531  }
    -
    2532  }
    -
    2533  }
    -
    2534  SECTION( "input validation" ) {
    -
    2535 
    -
    2536  int numRegs = 2;
    -
    2537  int numQubitsPerReg[] = {2,3};
    -
    2538  int regs[] = {0,1,2,3,4};
    +

    Definition at line 2079 of file test_operators.cpp.

    +
    2079  {
    +
    2080 
    +
    2081  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    2082 
    +
    2083  SECTION( "correctness" ) {
    +
    2084 
    +
    2085  // try every kind of binary encoding
    +
    2086  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    +
    2087 
    +
    2088  // try every possible number of registers
    +
    2089  // (between #qubits containing 1, and 1 containing #qubits)
    +
    2090  int numRegs;
    +
    2091  int maxNumRegs = 0;
    +
    2092  if (encoding == UNSIGNED)
    +
    2093  maxNumRegs = NUM_QUBITS;
    +
    2094  if (encoding == TWOS_COMPLEMENT)
    +
    2095  maxNumRegs = NUM_QUBITS/2; // floors
    +
    2096  numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
    +
    2097 
    +
    2098  // try every possible total number of involved qubits
    +
    2099  int totalNumQubits;
    +
    2100  int minTotalQubits = 0;
    +
    2101  if (encoding == UNSIGNED)
    +
    2102  // each register must contain at least 1 qubit
    +
    2103  minTotalQubits = numRegs;
    +
    2104  if (encoding == TWOS_COMPLEMENT)
    +
    2105  // each register must contain at least 2 qubits
    +
    2106  minTotalQubits = 2*numRegs;
    +
    2107  totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
    +
    2108 
    +
    2109  // try every qubits subset and ordering
    +
    2110  int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
    +
    2111 
    +
    2112  // assign each sub-reg its minimum length
    +
    2113  int unallocQubits = totalNumQubits;
    +
    2114  int numQubitsPerReg[numRegs];
    +
    2115  for (int i=0; i<numRegs; i++)
    +
    2116  if (encoding == UNSIGNED) {
    +
    2117  numQubitsPerReg[i] = 1;
    +
    2118  unallocQubits -= 1;
    +
    2119  }
    +
    2120  else if (encoding == TWOS_COMPLEMENT) {
    +
    2121  numQubitsPerReg[i] = 2;
    +
    2122  unallocQubits -= 2;
    +
    2123  }
    +
    2124  // and randomly allocate the remaining qubits between the registers
    +
    2125  while (unallocQubits > 0) {
    +
    2126  numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
    +
    2127  unallocQubits--;
    +
    2128  }
    +
    2129 
    +
    2130 
    +
    2131  // choose a random number of overrides (even overriding every amplitude)
    +
    2132  int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
    +
    2133 
    +
    2134  // randomise each override index (uniqueness isn't checked)
    +
    2135  long long int overrideInds[numOverrides*numRegs];
    +
    2136  int flatInd = 0;
    +
    2137  for (int v=0; v<numOverrides; v++) {
    +
    2138  for (int r=0; r<numRegs; r++) {
    +
    2139  if (encoding == UNSIGNED)
    +
    2140  overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
    +
    2141  else if (encoding == TWOS_COMPLEMENT)
    +
    2142  overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
    +
    2143  flatInd++;
    +
    2144  }
    +
    2145  }
    +
    2146 
    +
    2147  // override to a random phase
    +
    2148  qreal overridePhases[numOverrides];
    +
    2149  for (int v=0; v<numOverrides; v++)
    +
    2150  overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    +
    2151 
    +
    2152 
    +
    2153  // determine the values corresponding to each register for all basis states
    +
    2154  qreal regVals[1<<totalNumQubits][numRegs];
    +
    2155  for (long long int i=0; i<(1<<totalNumQubits); i++) {
    +
    2156 
    +
    2157  long long int bits = i;
    +
    2158  for (int r=0; r<numRegs; r++) {
    +
    2159  regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
    +
    2160  bits = bits >> numQubitsPerReg[r];
    +
    2161 
    +
    2162  if (encoding == TWOS_COMPLEMENT)
    +
    2163  regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
    +
    2164  }
    +
    2165  }
    +
    2166 
    +
    2167  /* produce a reference diagonal matrix which assumes the qubits are
    +
    2168  * contiguous and strictly increasing between the registers, and hence
    +
    2169  * only depends on the number of qubits in each register.
    +
    2170  */
    +
    2171  QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
    +
    2172 
    +
    2173 
    +
    2174  SECTION( "INVERSE_NORM" ) {
    +
    2175 
    +
    2176  enum phaseFunc func = INVERSE_NORM;
    +
    2177  qreal divPhase = getRandomReal(-4, 4);
    +
    2178  qreal params[] = {divPhase};
    +
    2179  int numParams = 1;
    +
    2180 
    +
    2181  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2182  qreal phase = 0;
    +
    2183  for (int r=0; r<numRegs; r++)
    +
    2184  phase += pow(regVals[i][r], 2);
    +
    2185  phase = (phase == 0.)? divPhase : 1/sqrt(phase);
    +
    2186  diagMatr[i][i] = expI(phase);
    +
    2187  }
    +
    2188  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2189 
    +
    2190  SECTION( "state-vector" ) {
    +
    2191 
    +
    2192  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2193  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2194  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2195  }
    +
    2196  SECTION( "density-matrix" ) {
    +
    2197 
    +
    2198  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2199  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2200  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2201  }
    +
    2202  }
    +
    2203  SECTION( "SCALED_NORM" ) {
    +
    2204 
    +
    2205  enum phaseFunc func = SCALED_NORM;
    +
    2206  qreal coeff = getRandomReal(-10, 10);
    +
    2207  qreal params[] = {coeff};
    +
    2208  int numParams = 1;
    +
    2209 
    +
    2210  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2211  qreal phase = 0;
    +
    2212  for (int r=0; r<numRegs; r++)
    +
    2213  phase += pow(regVals[i][r], 2);
    +
    2214  phase = coeff * sqrt(phase);
    +
    2215  diagMatr[i][i] = expI(phase);
    +
    2216  }
    +
    2217  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2218 
    +
    2219  SECTION( "state-vector" ) {
    +
    2220 
    +
    2221  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2222  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2223  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2224  }
    +
    2225  SECTION( "density-matrix" ) {
    +
    2226 
    +
    2227  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2228  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2229  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2230  }
    +
    2231  }
    +
    2232  SECTION( "SCALED_INVERSE_NORM" ) {
    +
    2233 
    +
    2234  enum phaseFunc func = SCALED_INVERSE_NORM;
    +
    2235  qreal coeff = getRandomReal(-10, 10);
    +
    2236  qreal divPhase = getRandomReal(-4, 4);
    +
    2237  qreal params[] = {coeff, divPhase};
    +
    2238  int numParams = 2;
    +
    2239 
    +
    2240  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2241  qreal phase = 0;
    +
    2242  for (int r=0; r<numRegs; r++)
    +
    2243  phase += pow(regVals[i][r], 2);
    +
    2244  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    +
    2245  diagMatr[i][i] = expI(phase);
    +
    2246  }
    +
    2247  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2248 
    +
    2249  SECTION( "state-vector" ) {
    +
    2250 
    +
    2251  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2252  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2253  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2254  }
    +
    2255  SECTION( "density-matrix" ) {
    +
    2256 
    +
    2257  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2258  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2259  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2260  }
    +
    2261  }
    +
    2262  SECTION( "SCALED_INVERSE_SHIFTED_NORM" ) {
    +
    2263 
    + +
    2265  int numParams = 2 + numRegs;
    +
    2266  qreal params[numParams];
    +
    2267  params[0] = getRandomReal(-10, 10); // scaling
    +
    2268  params[1] = getRandomReal(-4, 4); // divergence override
    +
    2269  for (int r=0; r<numRegs; r++)
    +
    2270  params[2+r] = getRandomReal(-8, 8); // shifts
    +
    2271 
    +
    2272  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2273  qreal phase = 0;
    +
    2274  for (int r=0; r<numRegs; r++)
    +
    2275  phase += pow(regVals[i][r] - params[2+r], 2);
    +
    2276  phase = sqrt(phase);
    +
    2277  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    2278  diagMatr[i][i] = expI(phase);
    +
    2279  }
    +
    2280  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2281 
    +
    2282  SECTION( "state-vector" ) {
    +
    2283 
    +
    2284  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2285  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2286  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2287  }
    +
    2288  SECTION( "density-matrix" ) {
    +
    2289 
    +
    2290  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2291  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2292  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2293  }
    +
    2294  }
    +
    2295  SECTION( "INVERSE_PRODUCT" ) {
    +
    2296 
    +
    2297  enum phaseFunc func = INVERSE_PRODUCT;
    +
    2298  qreal divPhase = getRandomReal(-4, 4);
    +
    2299  qreal params[] = {divPhase};
    +
    2300  int numParams = 1;
    +
    2301 
    +
    2302  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2303  qreal phase = 1;
    +
    2304  for (int r=0; r<numRegs; r++)
    +
    2305  phase *= regVals[i][r];
    +
    2306  phase = (phase == 0.)? divPhase : 1. / phase;
    +
    2307  diagMatr[i][i] = expI(phase);
    +
    2308  }
    +
    2309  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2310 
    +
    2311  SECTION( "state-vector" ) {
    +
    2312 
    +
    2313  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2314  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2315  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2316  }
    +
    2317  SECTION( "density-matrix" ) {
    +
    2318 
    +
    2319  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2320  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2321  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2322  }
    +
    2323  }
    +
    2324  SECTION( "SCALED_PRODUCT" ) {
    +
    2325 
    +
    2326  enum phaseFunc func = SCALED_PRODUCT;
    +
    2327  qreal coeff = getRandomReal(-10, 10);
    +
    2328  qreal params[] = {coeff};
    +
    2329  int numParams = 1;
    +
    2330 
    +
    2331  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2332  qreal phase = 1;
    +
    2333  for (int r=0; r<numRegs; r++)
    +
    2334  phase *= regVals[i][r];
    +
    2335  diagMatr[i][i] = expI(coeff * phase);
    +
    2336  }
    +
    2337  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2338 
    +
    2339  SECTION( "state-vector" ) {
    +
    2340 
    +
    2341  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2342  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2343  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2344  }
    +
    2345  SECTION( "density-matrix" ) {
    +
    2346 
    +
    2347  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2348  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2349  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2350  }
    +
    2351  }
    +
    2352  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    +
    2353 
    +
    2354  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    +
    2355  qreal coeff = getRandomReal(-10, 10);
    +
    2356  qreal divPhase = getRandomReal(-4, 4);
    +
    2357  qreal params[] = {coeff, divPhase};
    +
    2358  int numParams = 2;
    +
    2359 
    +
    2360  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2361  qreal phase = 1;
    +
    2362  for (int r=0; r<numRegs; r++)
    +
    2363  phase *= regVals[i][r];
    +
    2364  phase = (phase == 0)? divPhase : coeff / phase;
    +
    2365  diagMatr[i][i] = expI(phase);
    +
    2366  }
    +
    2367  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2368 
    +
    2369  SECTION( "state-vector" ) {
    +
    2370 
    +
    2371  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2372  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2373  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2374  }
    +
    2375  SECTION( "density-matrix" ) {
    +
    2376 
    +
    2377  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2378  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2379  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2380  }
    +
    2381  }
    +
    2382  SECTION( "INVERSE_DISTANCE" ) {
    +
    2383 
    +
    2384  enum phaseFunc func = INVERSE_DISTANCE;
    +
    2385  qreal divPhase = getRandomReal( -4, 4 );
    +
    2386  qreal params[] = {divPhase};
    +
    2387  int numParams = 1;
    +
    2388 
    +
    2389  // test only if there are an even number of registers
    +
    2390  if (numRegs%2 == 0) {
    +
    2391 
    +
    2392  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2393  qreal phase = 0;
    +
    2394  for (int r=0; r<numRegs; r+=2)
    +
    2395  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    2396  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    +
    2397  diagMatr[i][i] = expI(phase);
    +
    2398  }
    +
    2399  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2400  }
    +
    2401 
    +
    2402  SECTION( "state-vector" ) {
    +
    2403 
    +
    2404  if (numRegs%2 == 0) {
    +
    2405  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2406  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2407  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2408  }
    +
    2409  }
    +
    2410  SECTION( "density-matrix" ) {
    +
    2411 
    +
    2412  if (numRegs%2 == 0) {
    +
    2413  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2414  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2415  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2416  }
    +
    2417  }
    +
    2418  }
    +
    2419  SECTION( "SCALED_DISTANCE" ) {
    +
    2420 
    +
    2421  enum phaseFunc func = SCALED_DISTANCE;
    +
    2422  qreal coeff = getRandomReal( -10, 10 );
    +
    2423  qreal params[] = {coeff};
    +
    2424  int numParams = 1;
    +
    2425 
    +
    2426  // test only if there are an even number of registers
    +
    2427  if (numRegs%2 == 0) {
    +
    2428 
    +
    2429  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2430  qreal phase = 0;
    +
    2431  for (int r=0; r<numRegs; r+=2)
    +
    2432  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    2433  phase = coeff * sqrt(phase);
    +
    2434  diagMatr[i][i] = expI(phase);
    +
    2435  }
    +
    2436  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2437  }
    +
    2438 
    +
    2439  SECTION( "state-vector" ) {
    +
    2440 
    +
    2441  if (numRegs%2 == 0) {
    +
    2442  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2443  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2444  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2445  }
    +
    2446  }
    +
    2447  SECTION( "density-matrix" ) {
    +
    2448 
    +
    2449  if (numRegs%2 == 0) {
    +
    2450  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2451  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2452  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2453  }
    +
    2454  }
    +
    2455  }
    +
    2456  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    +
    2457 
    +
    2458  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    +
    2459  qreal coeff = getRandomReal( -10, 10 );
    +
    2460  qreal divPhase = getRandomReal( -4, 4 );
    +
    2461  qreal params[] = {coeff, divPhase};
    +
    2462  int numParams = 2;
    +
    2463 
    +
    2464  // test only if there are an even number of registers
    +
    2465  if (numRegs%2 == 0) {
    +
    2466 
    +
    2467  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2468  qreal phase = 0;
    +
    2469  for (int r=0; r<numRegs; r+=2)
    +
    2470  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    2471  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    +
    2472  diagMatr[i][i] = expI(phase);
    +
    2473  }
    +
    2474  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2475  }
    +
    2476 
    +
    2477  SECTION( "state-vector" ) {
    +
    2478 
    +
    2479  if (numRegs%2 == 0) {
    +
    2480  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2481  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2482  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2483  }
    +
    2484  }
    +
    2485  SECTION( "density-matrix" ) {
    +
    2486 
    +
    2487  if (numRegs%2 == 0) {
    +
    2488  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2489  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2490  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2491  }
    +
    2492  }
    +
    2493  }
    +
    2494  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    +
    2495 
    + +
    2497  int numParams = 2 + numRegs/2;
    +
    2498  qreal params[numParams];
    +
    2499 
    +
    2500  // test only if there are an even number of registers
    +
    2501  if (numRegs%2 == 0) {
    +
    2502 
    +
    2503  params[0] = getRandomReal( -10, 10 ); // scaling
    +
    2504  params[1] = getRandomReal( -4, 4 ); // divergence override
    +
    2505  for (int r=0; r<numRegs/2; r++)
    +
    2506  params[2+r] = getRandomReal( -8, 8 ); // shifts
    +
    2507 
    +
    2508  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2509  qreal phase = 0;
    +
    2510  for (int r=0; r<numRegs; r+=2)
    +
    2511  phase += pow(regVals[i][r]-regVals[i][r+1]-params[2+r/2], 2);
    +
    2512  phase = sqrt(phase);
    +
    2513  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    2514  diagMatr[i][i] = expI(phase);
    +
    2515  }
    +
    2516 
    +
    2517  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2518  }
    +
    2519 
    +
    2520  SECTION( "state-vector" ) {
    +
    2521 
    +
    2522  if (numRegs%2 == 0) {
    +
    2523  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2524  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2525  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2526  }
    +
    2527  }
    +
    2528  SECTION( "density-matrix" ) {
    +
    2529 
    +
    2530  if (numRegs%2 == 0) {
    +
    2531  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2532  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2533  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2534  }
    +
    2535  }
    +
    2536  }
    +
    2537  }
    +
    2538  SECTION( "input validation" ) {
    2539 
    -
    2540  SECTION( "number of registers" ) {
    -
    2541 
    -
    2542  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    -
    2543  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubit subregisters") );
    -
    2544  }
    -
    2545  SECTION( "number of qubits" ) {
    -
    2546 
    -
    2547  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    -
    2548  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubits") );
    -
    2549  }
    -
    2550  SECTION( "repetition of qubits" ) {
    -
    2551 
    -
    2552  regs[GENERATE(2,3,4)] = regs[1];
    -
    2553  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("The qubits must be unique") );
    -
    2554  }
    -
    2555  SECTION( "qubit indices" ) {
    -
    2556 
    -
    2557  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    -
    2558  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid qubit index") );
    -
    2559  }
    -
    2560  SECTION( "bit encoding name" ) {
    -
    2561 
    -
    2562  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    -
    2563  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid bit encoding") );
    -
    2564  }
    -
    2565  SECTION( "two's complement register" ) {
    -
    2566 
    -
    2567  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    -
    2568  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0, NULL, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    -
    2569  }
    -
    2570  SECTION( "phase function name" ) {
    -
    2571 
    -
    2572  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    -
    2573  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0, NULL, NULL, 0), Contains("Invalid named phase function") );
    -
    2574  }
    -
    2575  SECTION( "phase function parameters" ) {
    -
    2576 
    -
    2577  qreal params[numRegs + 3];
    -
    2578  for (int r=0; r<numRegs + 3; r++)
    -
    2579  params[r] = 0;
    +
    2540  int numRegs = 2;
    +
    2541  int numQubitsPerReg[] = {2,3};
    +
    2542  int regs[] = {0,1,2,3,4};
    +
    2543 
    +
    2544  SECTION( "number of registers" ) {
    +
    2545 
    +
    2546  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    +
    2547  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubit subregisters") );
    +
    2548  }
    +
    2549  SECTION( "number of qubits" ) {
    +
    2550 
    +
    2551  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    +
    2552  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubits") );
    +
    2553  }
    +
    2554  SECTION( "repetition of qubits" ) {
    +
    2555 
    +
    2556  regs[GENERATE(2,3,4)] = regs[1];
    +
    2557  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("The qubits must be unique") );
    +
    2558  }
    +
    2559  SECTION( "qubit indices" ) {
    +
    2560 
    +
    2561  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    +
    2562  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid qubit index") );
    +
    2563  }
    +
    2564  SECTION( "bit encoding name" ) {
    +
    2565 
    +
    2566  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    +
    2567  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid bit encoding") );
    +
    2568  }
    +
    2569  SECTION( "two's complement register" ) {
    +
    2570 
    +
    2571  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    +
    2572  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0, NULL, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    +
    2573  }
    +
    2574  SECTION( "phase function name" ) {
    +
    2575 
    +
    2576  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    +
    2577  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0, NULL, NULL, 0), Contains("Invalid named phase function") );
    +
    2578  }
    +
    2579  SECTION( "phase function parameters" ) {
    2580 
    -
    2581  SECTION( "no parameter functions" ) {
    -
    2582 
    -
    2583  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    -
    2584  int numParams = GENERATE( -1, 1, 2 );
    -
    2585  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2586  }
    -
    2587  SECTION( "single parameter functions" ) {
    -
    2588 
    - -
    2590  int numParams = GENERATE( -1, 0, 2 );
    -
    2591  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2592  }
    -
    2593  SECTION( "two parameter functions" ) {
    -
    2594 
    - -
    2596  int numParams = GENERATE( 0, 1, 3 );
    -
    2597  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2598  }
    -
    2599  SECTION( "shifted distance" ) {
    -
    2600 
    -
    2601  if (numRegs%2 == 0) {
    - -
    2603  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    -
    2604  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2605  }
    -
    2606  }
    -
    2607  SECTION( "shifted norm" ) {
    -
    2608 
    - -
    2610  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    -
    2611  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2612  }
    -
    2613  }
    -
    2614  SECTION( "distance pair registers" ) {
    -
    2615 
    -
    2616  int numQb[] = {1,1,1,1,1};
    -
    2617  int qb[] = {0,1,2,3,4};
    -
    2618 
    -
    2619  numRegs = GENERATE( 1, 3, 5 );
    -
    2620  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0, NULL, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    -
    2621  }
    -
    2622  SECTION( "number of overrides" ) {
    -
    2623 
    -
    2624  int numOverrides = -1;
    -
    2625  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides specified") );
    -
    2626  }
    -
    2627  SECTION( "override indices" ) {
    -
    2628 
    -
    2629  // numQubitsPerReg = {2, 3}
    -
    2630  int numOverrides = 3;
    -
    2631  long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
    -
    2632  qreal overridePhases[] = {.1, .1, .1};
    -
    2633 
    -
    2634  // first element of overrideInds coordinate is a 2 qubit register
    -
    2635  enum bitEncoding enc = UNSIGNED;
    -
    2636  int badInd = GENERATE(0, 2, 4);
    -
    2637  overrideInds[badInd] = GENERATE( -1, (1<<2) );
    -
    2638  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    -
    2639  overrideInds[badInd] = 0;
    -
    2640 
    -
    2641  // second element of overrideInds coordinate is a 3 qubit register
    -
    2642  badInd += 1;
    -
    2643  overrideInds[badInd] = GENERATE( -1, (1<<3) );
    -
    2644  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    -
    2645  overrideInds[badInd] = 0;
    -
    2646  badInd -= 1;
    -
    2647 
    -
    2648  enc = TWOS_COMPLEMENT;
    -
    2649  int minInd = -(1<<(numQubitsPerReg[0]-1));
    -
    2650  int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
    -
    2651  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    -
    2652  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    -
    2653  overrideInds[badInd] = 0;
    -
    2654 
    -
    2655  badInd++;
    -
    2656  minInd = -(1<<(numQubitsPerReg[1]-1));
    -
    2657  maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
    -
    2658  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    -
    2659  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    -
    2660  }
    -
    2661  }
    -
    2662  CLEANUP_TEST( quregVec, quregMatr );
    -
    2663 }
    +
    2581  qreal params[numRegs + 3];
    +
    2582  for (int r=0; r<numRegs + 3; r++)
    +
    2583  params[r] = 0;
    +
    2584 
    +
    2585  SECTION( "no parameter functions" ) {
    +
    2586 
    +
    2587  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    +
    2588  int numParams = GENERATE( -1, 1, 2 );
    +
    2589  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2590  }
    +
    2591  SECTION( "single parameter functions" ) {
    +
    2592 
    + +
    2594  int numParams = GENERATE( -1, 0, 2 );
    +
    2595  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2596  }
    +
    2597  SECTION( "two parameter functions" ) {
    +
    2598 
    + +
    2600  int numParams = GENERATE( 0, 1, 3 );
    +
    2601  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2602  }
    +
    2603  SECTION( "shifted distance" ) {
    +
    2604 
    +
    2605  if (numRegs%2 == 0) {
    + +
    2607  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    +
    2608  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2609  }
    +
    2610  }
    +
    2611  SECTION( "shifted norm" ) {
    +
    2612 
    + +
    2614  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    +
    2615  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2616  }
    +
    2617  }
    +
    2618  SECTION( "distance pair registers" ) {
    +
    2619 
    +
    2620  int numQb[] = {1,1,1,1,1};
    +
    2621  int qb[] = {0,1,2,3,4};
    +
    2622 
    +
    2623  numRegs = GENERATE( 1, 3, 5 );
    +
    2624  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0, NULL, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    +
    2625  }
    +
    2626  SECTION( "number of overrides" ) {
    +
    2627 
    +
    2628  int numOverrides = -1;
    +
    2629  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides specified") );
    +
    2630  }
    +
    2631  SECTION( "override indices" ) {
    +
    2632 
    +
    2633  // numQubitsPerReg = {2, 3}
    +
    2634  int numOverrides = 3;
    +
    2635  long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
    +
    2636  qreal overridePhases[] = {.1, .1, .1};
    +
    2637 
    +
    2638  // first element of overrideInds coordinate is a 2 qubit register
    +
    2639  enum bitEncoding enc = UNSIGNED;
    +
    2640  int badInd = GENERATE(0, 2, 4);
    +
    2641  overrideInds[badInd] = GENERATE( -1, (1<<2) );
    +
    2642  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    2643  overrideInds[badInd] = 0;
    +
    2644 
    +
    2645  // second element of overrideInds coordinate is a 3 qubit register
    +
    2646  badInd += 1;
    +
    2647  overrideInds[badInd] = GENERATE( -1, (1<<3) );
    +
    2648  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    2649  overrideInds[badInd] = 0;
    +
    2650  badInd -= 1;
    +
    2651 
    +
    2652  enc = TWOS_COMPLEMENT;
    +
    2653  int minInd = -(1<<(numQubitsPerReg[0]-1));
    +
    2654  int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
    +
    2655  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    +
    2656  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    +
    2657  overrideInds[badInd] = 0;
    +
    2658 
    +
    2659  badInd++;
    +
    2660  minInd = -(1<<(numQubitsPerReg[1]-1));
    +
    2661  maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
    +
    2662  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    +
    2663  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    +
    2664  }
    +
    2665  }
    +
    2666  CLEANUP_TEST( quregVec, quregMatr );
    +
    2667 }
    -

    References applyParamNamedPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, setDiagMatrixOverrides(), sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyParamNamedPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, DISTANCE, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), INVERSE_DISTANCE, INVERSE_NORM, INVERSE_PRODUCT, MAX_NUM_REGS_APPLY_ARBITRARY_PHASE, NORM, NUM_QUBITS, PREPARE_TEST, PRODUCT, qreal, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_SHIFTED_DISTANCE, SCALED_INVERSE_SHIFTED_NORM, SCALED_NORM, SCALED_PRODUCT, setDiagMatrixOverrides(), sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [13/123]

    +

    ◆ TEST_CASE() [13/124]

    @@ -3305,107 +3311,107 @@

    See also
    applyPauliHamil
    Author
    Tyson Jones
    -

    Definition at line 2671 of file test_operators.cpp.

    -
    2671  {
    -
    2672 
    - - - - -
    2677 
    -
    2678  initDebugState(vecIn);
    -
    2679  initDebugState(matIn);
    -
    2680 
    -
    2681  SECTION( "correctness" ) {
    -
    2682 
    -
    2683  /* it's too expensive to try every possible Pauli configuration, so
    -
    2684  * we'll try 10 random codes, and for each, random coefficients
    -
    2685  */
    -
    2686  GENERATE( range(0,10) );
    -
    2687 
    -
    2688  int numTerms = GENERATE( 1, 2, 10, 15 );
    -
    2689  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    2690  setRandomPauliSum(hamil);
    -
    2691  QMatrix refHamil = toQMatrix(hamil);
    -
    2692 
    -
    2693  SECTION( "state-vector" ) {
    -
    2694 
    -
    2695  QVector vecRef = toQVector(vecIn);
    -
    2696  applyPauliHamil(vecIn, hamil, vecOut);
    -
    2697 
    -
    2698  // ensure vecIn barely changes under precision
    -
    2699  REQUIRE( areEqual(vecIn, vecRef) );
    -
    2700 
    -
    2701  // ensure vecOut changed correctly
    -
    2702  REQUIRE( areEqual(vecOut, refHamil * vecRef) );
    -
    2703  }
    -
    2704  SECTION( "density-matrix" ) {
    -
    2705 
    -
    2706  QMatrix matRef = toQMatrix(matIn);
    -
    2707  applyPauliHamil(matIn, hamil, matOut);
    -
    2708 
    -
    2709  // ensure matIn barely changes under precision
    -
    2710  REQUIRE( areEqual(matIn, matRef) );
    -
    2711 
    -
    2712  // ensure matOut changed correctly
    -
    2713  REQUIRE( areEqual(matOut, refHamil * matRef, 1E2*REAL_EPS) );
    -
    2714  }
    -
    2715 
    -
    2716  destroyPauliHamil(hamil);
    -
    2717  }
    -
    2718  SECTION( "input validation" ) {
    +

    Definition at line 2675 of file test_operators.cpp.

    +
    2675  {
    +
    2676 
    + + + + +
    2681 
    +
    2682  initDebugState(vecIn);
    +
    2683  initDebugState(matIn);
    +
    2684 
    +
    2685  SECTION( "correctness" ) {
    +
    2686 
    +
    2687  /* it's too expensive to try every possible Pauli configuration, so
    +
    2688  * we'll try 10 random codes, and for each, random coefficients
    +
    2689  */
    +
    2690  GENERATE( range(0,10) );
    +
    2691 
    +
    2692  int numTerms = GENERATE( 1, 2, 10, 15 );
    +
    2693  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    +
    2694  setRandomPauliSum(hamil);
    +
    2695  QMatrix refHamil = toQMatrix(hamil);
    +
    2696 
    +
    2697  SECTION( "state-vector" ) {
    +
    2698 
    +
    2699  QVector vecRef = toQVector(vecIn);
    +
    2700  applyPauliHamil(vecIn, hamil, vecOut);
    +
    2701 
    +
    2702  // ensure vecIn barely changes under precision
    +
    2703  REQUIRE( areEqual(vecIn, vecRef) );
    +
    2704 
    +
    2705  // ensure vecOut changed correctly
    +
    2706  REQUIRE( areEqual(vecOut, refHamil * vecRef) );
    +
    2707  }
    +
    2708  SECTION( "density-matrix" ) {
    +
    2709 
    +
    2710  QMatrix matRef = toQMatrix(matIn);
    +
    2711  applyPauliHamil(matIn, hamil, matOut);
    +
    2712 
    +
    2713  // ensure matIn barely changes under precision
    +
    2714  REQUIRE( areEqual(matIn, matRef) );
    +
    2715 
    +
    2716  // ensure matOut changed correctly
    +
    2717  REQUIRE( areEqual(matOut, refHamil * matRef, 1E2*REAL_EPS) );
    +
    2718  }
    2719 
    -
    2720  SECTION( "pauli codes" ) {
    -
    2721 
    -
    2722  int numTerms = 3;
    -
    2723  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    2724 
    -
    2725  // make one pauli code wrong
    -
    2726  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    2727  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("Invalid Pauli code") );
    -
    2728 
    -
    2729  destroyPauliHamil(hamil);
    -
    2730  }
    -
    2731  SECTION( "qureg dimensions" ) {
    +
    2720  destroyPauliHamil(hamil);
    +
    2721  }
    +
    2722  SECTION( "input validation" ) {
    +
    2723 
    +
    2724  SECTION( "pauli codes" ) {
    +
    2725 
    +
    2726  int numTerms = 3;
    +
    2727  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    +
    2728 
    +
    2729  // make one pauli code wrong
    +
    2730  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    +
    2731  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("Invalid Pauli code") );
    2732 
    -
    2733  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    - -
    2735 
    -
    2736  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, badVec), Contains("Dimensions of the qubit registers don't match") );
    -
    2737 
    -
    2738  destroyQureg(badVec, QUEST_ENV);
    -
    2739  destroyPauliHamil(hamil);
    -
    2740  }
    -
    2741  SECTION( "qureg types" ) {
    -
    2742 
    - -
    2744 
    -
    2745  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    +
    2733  destroyPauliHamil(hamil);
    +
    2734  }
    +
    2735  SECTION( "qureg dimensions" ) {
    +
    2736 
    +
    2737  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    + +
    2739 
    +
    2740  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, badVec), Contains("Dimensions of the qubit registers don't match") );
    +
    2741 
    +
    2742  destroyQureg(badVec, QUEST_ENV);
    +
    2743  destroyPauliHamil(hamil);
    +
    2744  }
    +
    2745  SECTION( "qureg types" ) {
    2746 
    -
    2747  destroyPauliHamil(hamil);
    -
    2748  }
    -
    2749  SECTION( "matching hamiltonian qubits" ) {
    + +
    2748 
    +
    2749  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    2750 
    -
    2751  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    -
    2752 
    -
    2753  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("same number of qubits") );
    -
    2754  REQUIRE_THROWS_WITH( applyPauliHamil(matIn, hamil, matOut), Contains("same number of qubits") );
    -
    2755 
    -
    2756  destroyPauliHamil(hamil);
    -
    2757  }
    -
    2758  }
    -
    2759  destroyQureg(vecIn, QUEST_ENV);
    -
    2760  destroyQureg(vecOut, QUEST_ENV);
    -
    2761  destroyQureg(matIn, QUEST_ENV);
    -
    2762  destroyQureg(matOut, QUEST_ENV);
    -
    2763 }
    +
    2751  destroyPauliHamil(hamil);
    +
    2752  }
    +
    2753  SECTION( "matching hamiltonian qubits" ) {
    +
    2754 
    +
    2755  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    +
    2756 
    +
    2757  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("same number of qubits") );
    +
    2758  REQUIRE_THROWS_WITH( applyPauliHamil(matIn, hamil, matOut), Contains("same number of qubits") );
    +
    2759 
    +
    2760  destroyPauliHamil(hamil);
    +
    2761  }
    +
    2762  }
    +
    2763  destroyQureg(vecIn, QUEST_ENV);
    +
    2764  destroyQureg(vecOut, QUEST_ENV);
    +
    2765  destroyQureg(matIn, QUEST_ENV);
    +
    2766  destroyQureg(matOut, QUEST_ENV);
    +
    2767 }
    -

    References applyPauliHamil(), areEqual(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), initDebugState(), NUM_QUBITS, PauliHamil::pauliCodes, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    +

    References applyPauliHamil(), areEqual(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), initDebugState(), NUM_QUBITS, PauliHamil::pauliCodes, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [14/123]

    +

    ◆ TEST_CASE() [14/124]

    @@ -3432,103 +3438,103 @@

    See also
    applyPauliSum
    Author
    Tyson Jones
    -

    Definition at line 2771 of file test_operators.cpp.

    -
    2771  {
    -
    2772 
    - - - - -
    2777 
    -
    2778  initDebugState(vecIn);
    -
    2779  initDebugState(matIn);
    -
    2780 
    -
    2781  SECTION( "correctness" ) {
    -
    2782 
    -
    2783  /* it's too expensive to try ALL Pauli sequences, via
    -
    2784  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
    -
    2785  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    -
    2786  * Hence, we instead opt to repeatedly randomly generate pauliseqs
    -
    2787  */
    -
    2788  GENERATE( range(0,10) ); // gen 10 random pauli-codes
    -
    2789 
    -
    2790  int numTerms = GENERATE( 1, 2, 10, 15);
    -
    2791  int numPaulis = numTerms * NUM_QUBITS;
    -
    2792 
    -
    2793  // each test will use random coefficients
    -
    2794  qreal coeffs[numTerms];
    -
    2795  pauliOpType paulis[numPaulis];
    -
    2796  setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numTerms);
    -
    2797  QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numTerms);
    -
    2798 
    -
    2799  SECTION( "state-vector" ) {
    -
    2800 
    -
    2801  QVector vecRef = toQVector(vecIn);
    -
    2802  applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
    -
    2803 
    -
    2804  // ensure vecIn barely changes under precision
    -
    2805  REQUIRE( areEqual(vecIn, vecRef) );
    -
    2806 
    -
    2807  // ensure vecOut changed correctly
    -
    2808  REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
    -
    2809  }
    -
    2810  SECTION( "density-matrix" ) {
    -
    2811 
    -
    2812  QMatrix matRef = toQMatrix(matIn);
    -
    2813  applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
    -
    2814 
    -
    2815  // ensure matIn barely changes under precision
    -
    2816  REQUIRE( areEqual(matIn, matRef) );
    -
    2817 
    -
    2818  // ensure matOut changed correctly
    -
    2819  REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
    -
    2820  }
    -
    2821  }
    -
    2822  SECTION( "input validation" ) {
    -
    2823 
    -
    2824  SECTION( "number of terms" ) {
    -
    2825 
    -
    2826  int numTerms = GENERATE( -1, 0 );
    -
    2827  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), Contains("Invalid number of terms") );
    -
    2828  }
    -
    2829  SECTION( "pauli codes" ) {
    -
    2830 
    -
    2831  // valid codes
    -
    2832  int numTerms = 3;
    -
    2833  int numPaulis = numTerms*NUM_QUBITS;
    -
    2834  pauliOpType paulis[numPaulis];
    -
    2835  for (int i=0; i<numPaulis; i++)
    -
    2836  paulis[i] = PAULI_I;
    -
    2837 
    -
    2838  // make one invalid
    -
    2839  paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    2840  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), Contains("Invalid Pauli code") );
    -
    2841  }
    -
    2842  SECTION( "qureg dimensions" ) {
    -
    2843 
    -
    2844  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    -
    2845  pauliOpType paulis[NUM_QUBITS];
    -
    2846  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), Contains("Dimensions of the qubit registers don't match") );
    -
    2847  destroyQureg(badVec, QUEST_ENV);
    -
    2848  }
    -
    2849  SECTION( "qureg types" ) {
    -
    2850 
    -
    2851  pauliOpType paulis[NUM_QUBITS];
    -
    2852  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    2853  }
    -
    2854  }
    -
    2855  destroyQureg(vecIn, QUEST_ENV);
    -
    2856  destroyQureg(vecOut, QUEST_ENV);
    -
    2857  destroyQureg(matIn, QUEST_ENV);
    -
    2858  destroyQureg(matOut, QUEST_ENV);
    -
    2859 }
    +

    Definition at line 2775 of file test_operators.cpp.

    +
    2775  {
    +
    2776 
    + + + + +
    2781 
    +
    2782  initDebugState(vecIn);
    +
    2783  initDebugState(matIn);
    +
    2784 
    +
    2785  SECTION( "correctness" ) {
    +
    2786 
    +
    2787  /* it's too expensive to try ALL Pauli sequences, via
    +
    2788  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
    +
    2789  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    +
    2790  * Hence, we instead opt to repeatedly randomly generate pauliseqs
    +
    2791  */
    +
    2792  GENERATE( range(0,10) ); // gen 10 random pauli-codes
    +
    2793 
    +
    2794  int numTerms = GENERATE( 1, 2, 10, 15);
    +
    2795  int numPaulis = numTerms * NUM_QUBITS;
    +
    2796 
    +
    2797  // each test will use random coefficients
    +
    2798  qreal coeffs[numTerms];
    +
    2799  pauliOpType paulis[numPaulis];
    +
    2800  setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numTerms);
    +
    2801  QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numTerms);
    +
    2802 
    +
    2803  SECTION( "state-vector" ) {
    +
    2804 
    +
    2805  QVector vecRef = toQVector(vecIn);
    +
    2806  applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
    +
    2807 
    +
    2808  // ensure vecIn barely changes under precision
    +
    2809  REQUIRE( areEqual(vecIn, vecRef) );
    +
    2810 
    +
    2811  // ensure vecOut changed correctly
    +
    2812  REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
    +
    2813  }
    +
    2814  SECTION( "density-matrix" ) {
    +
    2815 
    +
    2816  QMatrix matRef = toQMatrix(matIn);
    +
    2817  applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
    +
    2818 
    +
    2819  // ensure matIn barely changes under precision
    +
    2820  REQUIRE( areEqual(matIn, matRef) );
    +
    2821 
    +
    2822  // ensure matOut changed correctly
    +
    2823  REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
    +
    2824  }
    +
    2825  }
    +
    2826  SECTION( "input validation" ) {
    +
    2827 
    +
    2828  SECTION( "number of terms" ) {
    +
    2829 
    +
    2830  int numTerms = GENERATE( -1, 0 );
    +
    2831  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), Contains("Invalid number of terms") );
    +
    2832  }
    +
    2833  SECTION( "pauli codes" ) {
    +
    2834 
    +
    2835  // valid codes
    +
    2836  int numTerms = 3;
    +
    2837  int numPaulis = numTerms*NUM_QUBITS;
    +
    2838  pauliOpType paulis[numPaulis];
    +
    2839  for (int i=0; i<numPaulis; i++)
    +
    2840  paulis[i] = PAULI_I;
    +
    2841 
    +
    2842  // make one invalid
    +
    2843  paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
    +
    2844  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), Contains("Invalid Pauli code") );
    +
    2845  }
    +
    2846  SECTION( "qureg dimensions" ) {
    +
    2847 
    +
    2848  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    +
    2849  pauliOpType paulis[NUM_QUBITS];
    +
    2850  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), Contains("Dimensions of the qubit registers don't match") );
    +
    2851  destroyQureg(badVec, QUEST_ENV);
    +
    2852  }
    +
    2853  SECTION( "qureg types" ) {
    +
    2854 
    +
    2855  pauliOpType paulis[NUM_QUBITS];
    +
    2856  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    +
    2857  }
    +
    2858  }
    +
    2859  destroyQureg(vecIn, QUEST_ENV);
    +
    2860  destroyQureg(vecOut, QUEST_ENV);
    +
    2861  destroyQureg(matIn, QUEST_ENV);
    +
    2862  destroyQureg(matOut, QUEST_ENV);
    +
    2863 }
    -

    References applyPauliSum(), areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), NUM_QUBITS, PAULI_I, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    +

    References applyPauliSum(), areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), NUM_QUBITS, PAULI_I, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [15/123]

    +

    ◆ TEST_CASE() [15/124]

    @@ -3555,137 +3561,137 @@

    See also
    applyPhaseFunc
    Author
    Tyson Jones
    -

    Definition at line 2867 of file test_operators.cpp.

    -
    2867  {
    -
    2868 
    -
    2869  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2870 
    -
    2871  SECTION( "correctness" ) {
    -
    2872 
    -
    2873  // try every kind of binary encodings
    -
    2874  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    -
    2875 
    -
    2876  // try every sub-register size
    -
    2877  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    -
    2878 
    -
    2879  // force at least 2 qubits in two's compement though
    -
    2880  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    -
    2881  numQubits++;
    +

    Definition at line 2871 of file test_operators.cpp.

    +
    2871  {
    +
    2872 
    +
    2873  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    2874 
    +
    2875  SECTION( "correctness" ) {
    +
    2876 
    +
    2877  // try every kind of binary encodings
    +
    2878  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    +
    2879 
    +
    2880  // try every sub-register size
    +
    2881  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    2882 
    -
    2883  // try every possible sub-register
    -
    2884  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    -
    2885 
    -
    2886  // choose a random number of terms in the phase function
    -
    2887  int numTerms = getRandomInt(1, 5);
    -
    2888 
    -
    2889  // populate the phase function with random but POSITIVE-power terms,
    -
    2890  // and in two's complement mode, strictly integer powers
    -
    2891  qreal coeffs[numTerms];
    -
    2892  qreal expons[numTerms];
    -
    2893  for (int t=0; t<numTerms; t++) {
    -
    2894  coeffs[t] = getRandomReal(-10,10);
    -
    2895  if (encoding == TWOS_COMPLEMENT)
    -
    2896  expons[t] = getRandomInt(0, 3+1); // repetition of power is ok
    -
    2897  else
    -
    2898  expons[t] = getRandomReal(0, 3);
    -
    2899  }
    -
    2900 
    -
    2901  // build a reference diagonal matrix, on the reduced Hilbert space
    -
    2902  QMatrix matr = getZeroMatrix( 1 << numQubits );
    -
    2903  for (size_t i=0; i<matr.size(); i++) {
    -
    2904 
    -
    2905  long long int ind = 0;
    -
    2906  if (encoding == UNSIGNED)
    -
    2907  ind = i;
    -
    2908  if (encoding == TWOS_COMPLEMENT)
    -
    2909  ind = getTwosComplement(i, numQubits);
    -
    2910 
    -
    2911  qreal phase = 0;
    -
    2912  for (int t=0; t<numTerms; t++)
    -
    2913  phase += coeffs[t] * pow(ind, expons[t]);
    -
    2914 
    -
    2915  matr[i][i] = expI(phase);
    -
    2916  }
    -
    2917 
    -
    2918  SECTION( "state-vector" ) {
    -
    2919 
    -
    2920  applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms);
    -
    2921  applyReferenceOp(refVec, qubits, numQubits, matr);
    -
    2922  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    -
    2923  }
    -
    2924  SECTION( "density-matrix" ) {
    -
    2925 
    -
    2926  applyPhaseFunc(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms);
    -
    2927  applyReferenceOp(refMatr, qubits, numQubits, matr);
    -
    2928  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    -
    2929  }
    -
    2930  }
    -
    2931  SECTION( "input validation" ) {
    -
    2932 
    -
    2933  int numQubits = 3;
    -
    2934  int qubits[] = {0,1,2};
    -
    2935 
    -
    2936  SECTION( "number of qubits" ) {
    -
    2937 
    -
    2938  numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    -
    2939  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid number of qubits") );
    -
    2940  }
    -
    2941  SECTION( "repetition of qubits" ) {
    -
    2942 
    -
    2943  qubits[GENERATE(1,2)] = qubits[0];
    -
    2944  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("The qubits must be unique") );
    -
    2945  }
    -
    2946  SECTION( "qubit indices" ) {
    -
    2947 
    -
    2948  int inv = GENERATE( -1, NUM_QUBITS );
    -
    2949  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    -
    2950  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid qubit index") );
    -
    2951  }
    -
    2952  SECTION( "number of terms" ) {
    -
    2953 
    -
    2954  int numTerms = GENERATE( -1, 0 );
    -
    2955  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms), Contains("Invalid number of terms in the phase function") );
    -
    2956  }
    -
    2957  SECTION( "bit encoding name" ) {
    -
    2958 
    -
    2959  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    -
    2960  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, enc, NULL, NULL, 1), Contains("Invalid bit encoding") );
    -
    2961  }
    -
    2962  SECTION( "two's complement register" ) {
    -
    2963 
    -
    2964  numQubits = 1;
    -
    2965  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    -
    2966  }
    -
    2967  SECTION( "fractional exponent" ) {
    -
    2968 
    -
    2969  int numTerms = 3;
    -
    2970  qreal coeffs[] = {0,0,0};
    -
    2971  qreal expos[] = {1,2,3};
    -
    2972  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    -
    2973 
    -
    2974  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    -
    2975  }
    -
    2976  SECTION( "negative exponent" ) {
    -
    2977 
    -
    2978  int numTerms = 3;
    -
    2979  qreal coeffs[] = {0,0,0};
    -
    2980  qreal expos[] = {1,2,3};
    -
    2981  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2, -1.5 );
    -
    2982 
    -
    2983  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    -
    2984 
    -
    2985  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    -
    2986  }
    -
    2987  }
    -
    2988  CLEANUP_TEST( quregVec, quregMatr );
    -
    2989 }
    +
    2883  // force at least 2 qubits in two's compement though
    +
    2884  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    +
    2885  numQubits++;
    +
    2886 
    +
    2887  // try every possible sub-register
    +
    2888  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    +
    2889 
    +
    2890  // choose a random number of terms in the phase function
    +
    2891  int numTerms = getRandomInt(1, 5);
    +
    2892 
    +
    2893  // populate the phase function with random but POSITIVE-power terms,
    +
    2894  // and in two's complement mode, strictly integer powers
    +
    2895  qreal coeffs[numTerms];
    +
    2896  qreal expons[numTerms];
    +
    2897  for (int t=0; t<numTerms; t++) {
    +
    2898  coeffs[t] = getRandomReal(-10,10);
    +
    2899  if (encoding == TWOS_COMPLEMENT)
    +
    2900  expons[t] = getRandomInt(0, 3+1); // repetition of power is ok
    +
    2901  else
    +
    2902  expons[t] = getRandomReal(0, 3);
    +
    2903  }
    +
    2904 
    +
    2905  // build a reference diagonal matrix, on the reduced Hilbert space
    +
    2906  QMatrix matr = getZeroMatrix( 1 << numQubits );
    +
    2907  for (size_t i=0; i<matr.size(); i++) {
    +
    2908 
    +
    2909  long long int ind = 0;
    +
    2910  if (encoding == UNSIGNED)
    +
    2911  ind = i;
    +
    2912  if (encoding == TWOS_COMPLEMENT)
    +
    2913  ind = getTwosComplement(i, numQubits);
    +
    2914 
    +
    2915  qreal phase = 0;
    +
    2916  for (int t=0; t<numTerms; t++)
    +
    2917  phase += coeffs[t] * pow(ind, expons[t]);
    +
    2918 
    +
    2919  matr[i][i] = expI(phase);
    +
    2920  }
    +
    2921 
    +
    2922  SECTION( "state-vector" ) {
    +
    2923 
    +
    2924  applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms);
    +
    2925  applyReferenceOp(refVec, qubits, numQubits, matr);
    +
    2926  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    +
    2927  }
    +
    2928  SECTION( "density-matrix" ) {
    +
    2929 
    +
    2930  applyPhaseFunc(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms);
    +
    2931  applyReferenceOp(refMatr, qubits, numQubits, matr);
    +
    2932  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    +
    2933  }
    +
    2934  }
    +
    2935  SECTION( "input validation" ) {
    +
    2936 
    +
    2937  int numQubits = 3;
    +
    2938  int qubits[] = {0,1,2};
    +
    2939 
    +
    2940  SECTION( "number of qubits" ) {
    +
    2941 
    +
    2942  numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    +
    2943  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid number of qubits") );
    +
    2944  }
    +
    2945  SECTION( "repetition of qubits" ) {
    +
    2946 
    +
    2947  qubits[GENERATE(1,2)] = qubits[0];
    +
    2948  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("The qubits must be unique") );
    +
    2949  }
    +
    2950  SECTION( "qubit indices" ) {
    +
    2951 
    +
    2952  int inv = GENERATE( -1, NUM_QUBITS );
    +
    2953  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    +
    2954  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid qubit index") );
    +
    2955  }
    +
    2956  SECTION( "number of terms" ) {
    +
    2957 
    +
    2958  int numTerms = GENERATE( -1, 0 );
    +
    2959  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms), Contains("Invalid number of terms in the phase function") );
    +
    2960  }
    +
    2961  SECTION( "bit encoding name" ) {
    +
    2962 
    +
    2963  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    +
    2964  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, enc, NULL, NULL, 1), Contains("Invalid bit encoding") );
    +
    2965  }
    +
    2966  SECTION( "two's complement register" ) {
    +
    2967 
    +
    2968  numQubits = 1;
    +
    2969  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    +
    2970  }
    +
    2971  SECTION( "fractional exponent" ) {
    +
    2972 
    +
    2973  int numTerms = 3;
    +
    2974  qreal coeffs[] = {0,0,0};
    +
    2975  qreal expos[] = {1,2,3};
    +
    2976  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    +
    2977 
    +
    2978  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    +
    2979  }
    +
    2980  SECTION( "negative exponent" ) {
    +
    2981 
    +
    2982  int numTerms = 3;
    +
    2983  qreal coeffs[] = {0,0,0};
    +
    2984  qreal expos[] = {1,2,3};
    +
    2985  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2, -1.5 );
    +
    2986 
    +
    2987  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    +
    2988 
    +
    2989  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    +
    2990  }
    +
    2991  }
    +
    2992  CLEANUP_TEST( quregVec, quregMatr );
    +
    2993 }
    -

    References applyPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, qreal, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyPhaseFunc(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, qreal, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    -

    ◆ TEST_CASE() [16/123]

    +

    ◆ TEST_CASE() [16/124]

    @@ -3712,220 +3718,382 @@

    See also
    applyPhaseFuncOverrides
    Author
    Tyson Jones
    -

    Definition at line 2997 of file test_operators.cpp.

    -
    2997  {
    -
    2998 
    -
    2999  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    3000 
    -
    3001  SECTION( "correctness" ) {
    -
    3002 
    -
    3003  // try every kind of binary encodings
    -
    3004  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    -
    3005 
    -
    3006  // try every sub-register size
    -
    3007  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    -
    3008 
    -
    3009  // force at least 2 qubits in two's compement though
    -
    3010  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    -
    3011  numQubits++;
    +

    Definition at line 3001 of file test_operators.cpp.

    +
    3001  {
    +
    3002 
    +
    3003  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    3004 
    +
    3005  SECTION( "correctness" ) {
    +
    3006 
    +
    3007  // try every kind of binary encodings
    +
    3008  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    +
    3009 
    +
    3010  // try every sub-register size
    +
    3011  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    3012 
    -
    3013  // try every possible sub-register
    -
    3014  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    -
    3015 
    -
    3016  // choose a random number of terms in the phase function
    -
    3017  int numTerms = getRandomInt(1, 21);
    -
    3018 
    -
    3019  // populate the phase function with random powers.
    -
    3020  // this includes negative powers, so we must always override 0.
    -
    3021  // in two's complement, we must use only integer powers
    -
    3022  qreal coeffs[numTerms];
    -
    3023  qreal expons[numTerms];
    -
    3024  for (int t=0; t<numTerms; t++) {
    -
    3025  coeffs[t] = getRandomReal(-10,10);
    -
    3026  if (encoding == TWOS_COMPLEMENT)
    -
    3027  expons[t] = getRandomInt(-3, 3+1); // note we COULD do getRandomReal(), and override all negatives
    -
    3028  else
    -
    3029  expons[t] = getRandomReal(-3, 3);
    -
    3030  }
    -
    3031 
    -
    3032  // choose a random number of overrides (even overriding every amplitude)
    -
    3033  int numOverrides = getRandomInt(1, (1<<numQubits) + 1);
    -
    3034 
    -
    3035  // randomise each override index (uniqueness isn't checked)
    -
    3036  long long int overrideInds[numOverrides];
    -
    3037  overrideInds[0] = 0LL;
    -
    3038  for (int i=1; i<numOverrides; i++)
    -
    3039  if (encoding == UNSIGNED)
    -
    3040  overrideInds[i] = getRandomInt(0, 1<<numQubits);
    -
    3041  else if (encoding == TWOS_COMPLEMENT)
    -
    3042  overrideInds[i] = getRandomInt(-(1<<(numQubits-1)), (1<<(numQubits-1))-1);
    -
    3043 
    -
    3044  // override to a random phase
    -
    3045  qreal overridePhases[numOverrides];
    -
    3046  for (int i=0; i<numOverrides; i++)
    -
    3047  overridePhases[i] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    -
    3048 
    -
    3049  // build a reference diagonal matrix, on the reduced Hilbert space
    -
    3050  QMatrix matr = getZeroMatrix( 1 << numQubits );
    -
    3051  for (size_t i=0; i<matr.size(); i++) {
    +
    3013  // force at least 2 qubits in two's compement though
    +
    3014  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    +
    3015  numQubits++;
    +
    3016 
    +
    3017  // try every possible sub-register
    +
    3018  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    +
    3019 
    +
    3020  // choose a random number of terms in the phase function
    +
    3021  int numTerms = getRandomInt(1, 21);
    +
    3022 
    +
    3023  // populate the phase function with random powers.
    +
    3024  // this includes negative powers, so we must always override 0.
    +
    3025  // in two's complement, we must use only integer powers
    +
    3026  qreal coeffs[numTerms];
    +
    3027  qreal expons[numTerms];
    +
    3028  for (int t=0; t<numTerms; t++) {
    +
    3029  coeffs[t] = getRandomReal(-10,10);
    +
    3030  if (encoding == TWOS_COMPLEMENT)
    +
    3031  expons[t] = getRandomInt(-3, 3+1); // note we COULD do getRandomReal(), and override all negatives
    +
    3032  else
    +
    3033  expons[t] = getRandomReal(-3, 3);
    +
    3034  }
    +
    3035 
    +
    3036  // choose a random number of overrides (even overriding every amplitude)
    +
    3037  int numOverrides = getRandomInt(1, (1<<numQubits) + 1);
    +
    3038 
    +
    3039  // randomise each override index (uniqueness isn't checked)
    +
    3040  long long int overrideInds[numOverrides];
    +
    3041  overrideInds[0] = 0LL;
    +
    3042  for (int i=1; i<numOverrides; i++)
    +
    3043  if (encoding == UNSIGNED)
    +
    3044  overrideInds[i] = getRandomInt(0, 1<<numQubits);
    +
    3045  else if (encoding == TWOS_COMPLEMENT)
    +
    3046  overrideInds[i] = getRandomInt(-(1<<(numQubits-1)), (1<<(numQubits-1))-1);
    +
    3047 
    +
    3048  // override to a random phase
    +
    3049  qreal overridePhases[numOverrides];
    +
    3050  for (int i=0; i<numOverrides; i++)
    +
    3051  overridePhases[i] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    3052 
    -
    3053  long long int ind = 0;
    -
    3054  if (encoding == UNSIGNED)
    -
    3055  ind = i;
    -
    3056  if (encoding == TWOS_COMPLEMENT)
    -
    3057  ind = getTwosComplement(i, numQubits);
    -
    3058 
    -
    3059  // reference diagonal matrix incorporates overriden phases
    -
    3060  qreal phase;
    -
    3061  bool overriden = false;
    -
    3062  for (int v=0; v<numOverrides; v++) {
    -
    3063  if (ind == overrideInds[v]) {
    -
    3064  phase = overridePhases[v];
    -
    3065  overriden = true;
    -
    3066  break;
    -
    3067  }
    -
    3068  }
    -
    3069 
    -
    3070  if (!overriden) {
    -
    3071  phase = 0;
    -
    3072  for (int t=0; t<numTerms; t++)
    -
    3073  phase += coeffs[t] * pow(ind, expons[t]);
    -
    3074  }
    -
    3075 
    -
    3076  matr[i][i] = expI(phase);
    -
    3077  }
    -
    3078 
    -
    3079  SECTION( "state-vector" ) {
    -
    3080 
    -
    3081  applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    -
    3082  applyReferenceOp(refVec, qubits, numQubits, matr);
    -
    3083  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    -
    3084  }
    -
    3085  SECTION( "density-matrix" ) {
    -
    3086 
    -
    3087  applyPhaseFuncOverrides(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    -
    3088  applyReferenceOp(refMatr, qubits, numQubits, matr);
    -
    3089  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    -
    3090  }
    -
    3091  }
    -
    3092  SECTION( "input validation" ) {
    -
    3093 
    -
    3094  int numQubits = 3;
    -
    3095  int qubits[] = {0,1,2};
    -
    3096 
    -
    3097  SECTION( "number of qubits" ) {
    -
    3098 
    -
    3099  int numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    -
    3100  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid number of qubits") );
    -
    3101  }
    -
    3102  SECTION( "repetition qubits" ) {
    -
    3103 
    -
    3104  qubits[GENERATE(1,2)] = qubits[0];
    -
    3105  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("The qubits must be unique") );
    -
    3106  }
    -
    3107  SECTION( "qubit indices" ) {
    -
    3108 
    -
    3109  int inv = GENERATE( -1, NUM_QUBITS );
    -
    3110  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    -
    3111  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid qubit index") );
    -
    3112  }
    -
    3113  SECTION( "number of terms" ) {
    -
    3114 
    -
    3115  int numTerms = GENERATE( -1, 0 );
    -
    3116  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms, NULL, NULL, 0), Contains("Invalid number of terms in the phase function") );
    -
    3117  }
    -
    3118  SECTION( "bit encoding name" ) {
    -
    3119 
    -
    3120  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    -
    3121  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, enc, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid bit encoding") );
    -
    3122  }
    -
    3123  SECTION( "two's complement register" ) {
    -
    3124 
    -
    3125  numQubits = 1;
    -
    3126  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1, NULL, NULL, 0), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    -
    3127  }
    -
    3128  SECTION( "number of overrides" ) {
    -
    3129 
    -
    3130  qreal dummyTerms[] = {0};
    -
    3131 
    -
    3132  int numOverrides = GENERATE_COPY( -1, 1 + (1<<numQubits) );
    -
    3133  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, dummyTerms, dummyTerms, 1, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides") );
    -
    3134  }
    -
    3135  SECTION( "override indices" ) {
    -
    3136 
    -
    3137  int numOverrides = 3;
    -
    3138  long long int overrideInds[] = {0,1,2};
    -
    3139  qreal overridePhases[] = {.1,.1,.1};
    -
    3140  qreal dummyTerms[] = {0};
    -
    3141 
    -
    3142  enum bitEncoding encoding = UNSIGNED;
    -
    3143  overrideInds[GENERATE(0,1,2)] = GENERATE_COPY( -1, (1<<numQubits) );
    -
    3144  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    3053  // build a reference diagonal matrix, on the reduced Hilbert space
    +
    3054  QMatrix matr = getZeroMatrix( 1 << numQubits );
    +
    3055  for (size_t i=0; i<matr.size(); i++) {
    +
    3056 
    +
    3057  long long int ind = 0;
    +
    3058  if (encoding == UNSIGNED)
    +
    3059  ind = i;
    +
    3060  if (encoding == TWOS_COMPLEMENT)
    +
    3061  ind = getTwosComplement(i, numQubits);
    +
    3062 
    +
    3063  // reference diagonal matrix incorporates overriden phases
    +
    3064  qreal phase;
    +
    3065  bool overriden = false;
    +
    3066  for (int v=0; v<numOverrides; v++) {
    +
    3067  if (ind == overrideInds[v]) {
    +
    3068  phase = overridePhases[v];
    +
    3069  overriden = true;
    +
    3070  break;
    +
    3071  }
    +
    3072  }
    +
    3073 
    +
    3074  if (!overriden) {
    +
    3075  phase = 0;
    +
    3076  for (int t=0; t<numTerms; t++)
    +
    3077  phase += coeffs[t] * pow(ind, expons[t]);
    +
    3078  }
    +
    3079 
    +
    3080  matr[i][i] = expI(phase);
    +
    3081  }
    +
    3082 
    +
    3083  SECTION( "state-vector" ) {
    +
    3084 
    +
    3085  applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    +
    3086  applyReferenceOp(refVec, qubits, numQubits, matr);
    +
    3087  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    +
    3088  }
    +
    3089  SECTION( "density-matrix" ) {
    +
    3090 
    +
    3091  applyPhaseFuncOverrides(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    +
    3092  applyReferenceOp(refMatr, qubits, numQubits, matr);
    +
    3093  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    +
    3094  }
    +
    3095  }
    +
    3096  SECTION( "input validation" ) {
    +
    3097 
    +
    3098  int numQubits = 3;
    +
    3099  int qubits[] = {0,1,2};
    +
    3100 
    +
    3101  SECTION( "number of qubits" ) {
    +
    3102 
    +
    3103  int numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    +
    3104  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid number of qubits") );
    +
    3105  }
    +
    3106  SECTION( "repetition qubits" ) {
    +
    3107 
    +
    3108  qubits[GENERATE(1,2)] = qubits[0];
    +
    3109  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("The qubits must be unique") );
    +
    3110  }
    +
    3111  SECTION( "qubit indices" ) {
    +
    3112 
    +
    3113  int inv = GENERATE( -1, NUM_QUBITS );
    +
    3114  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    +
    3115  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid qubit index") );
    +
    3116  }
    +
    3117  SECTION( "number of terms" ) {
    +
    3118 
    +
    3119  int numTerms = GENERATE( -1, 0 );
    +
    3120  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms, NULL, NULL, 0), Contains("Invalid number of terms in the phase function") );
    +
    3121  }
    +
    3122  SECTION( "bit encoding name" ) {
    +
    3123 
    +
    3124  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    +
    3125  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, enc, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid bit encoding") );
    +
    3126  }
    +
    3127  SECTION( "two's complement register" ) {
    +
    3128 
    +
    3129  numQubits = 1;
    +
    3130  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1, NULL, NULL, 0), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    +
    3131  }
    +
    3132  SECTION( "number of overrides" ) {
    +
    3133 
    +
    3134  qreal dummyTerms[] = {0};
    +
    3135 
    +
    3136  int numOverrides = GENERATE_COPY( -1, 1 + (1<<numQubits) );
    +
    3137  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, dummyTerms, dummyTerms, 1, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides") );
    +
    3138  }
    +
    3139  SECTION( "override indices" ) {
    +
    3140 
    +
    3141  int numOverrides = 3;
    +
    3142  long long int overrideInds[] = {0,1,2};
    +
    3143  qreal overridePhases[] = {.1,.1,.1};
    +
    3144  qreal dummyTerms[] = {0};
    3145 
    -
    3146  encoding = TWOS_COMPLEMENT;
    -
    3147  long long int newInds[] = {0,1,2};
    -
    3148  int minInd = -(1<<(numQubits-1));
    -
    3149  int maxInd = (1<<(numQubits-1)) -1;
    -
    3150  newInds[GENERATE(0,1,2)] = GENERATE_COPY( minInd-1, maxInd+1 );
    -
    3151  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, newInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    -
    3152  }
    -
    3153  SECTION( "fractional exponent" ) {
    -
    3154 
    -
    3155  int numTerms = 3;
    -
    3156  qreal coeffs[] = {0,0,0};
    -
    3157  qreal expos[] = {1,2,3};
    +
    3146  enum bitEncoding encoding = UNSIGNED;
    +
    3147  overrideInds[GENERATE(0,1,2)] = GENERATE_COPY( -1, (1<<numQubits) );
    +
    3148  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    3149 
    +
    3150  encoding = TWOS_COMPLEMENT;
    +
    3151  long long int newInds[] = {0,1,2};
    +
    3152  int minInd = -(1<<(numQubits-1));
    +
    3153  int maxInd = (1<<(numQubits-1)) -1;
    +
    3154  newInds[GENERATE(0,1,2)] = GENERATE_COPY( minInd-1, maxInd+1 );
    +
    3155  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, newInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    +
    3156  }
    +
    3157  SECTION( "fractional exponent" ) {
    3158 
    -
    3159  // make one exponent fractional, thereby requiring negative overrides
    -
    3160  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    -
    3161 
    -
    3162  // catch when no negative indices are overridden
    -
    3163  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, NULL, NULL, 0), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    -
    3164 
    -
    3165  int numNegs = 1 << (numQubits-1);
    -
    3166  long long int overrideInds[numNegs];
    -
    3167  qreal overridePhases[numNegs];
    -
    3168  for (int i=0; i<numNegs; i++) {
    -
    3169  overrideInds[i] = -(i+1);
    -
    3170  overridePhases[i] = 0;
    -
    3171  }
    -
    3172 
    -
    3173  // ensure no throw when all are overriden
    -
    3174  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs) );
    -
    3175 
    -
    3176  // catch when at least one isn't overriden
    -
    3177  overrideInds[GENERATE_COPY( range(0,numNegs) )] = 0; // override a non-negative
    -
    3178  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    -
    3179  }
    -
    3180  SECTION( "negative exponent" ) {
    -
    3181 
    -
    3182  int numTerms = 3;
    -
    3183  qreal coeffs[] = {0,0,0};
    -
    3184  qreal expos[] = {1,2,3};
    -
    3185  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2 );
    -
    3186 
    -
    3187  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    -
    3188 
    -
    3189  // test both when giving no overrides, and giving all non-zero overrides
    -
    3190  int numOverrides = GENERATE( 0, 3 );
    -
    3191  long long int overrideInds[] = {1,2,3};
    -
    3192  qreal overridePhases[] = {0,0,0};
    -
    3193  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    -
    3194 
    -
    3195  // but ensure that when the zero IS overriden (anywhere), there's no error
    -
    3196  numOverrides = 3;
    -
    3197  overrideInds[GENERATE_COPY(range(0,numOverrides))] = 0;
    -
    3198  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides) );
    -
    3199  }
    -
    3200  }
    -
    3201  CLEANUP_TEST( quregVec, quregMatr );
    -
    3202 }
    +
    3159  int numTerms = 3;
    +
    3160  qreal coeffs[] = {0,0,0};
    +
    3161  qreal expos[] = {1,2,3};
    +
    3162 
    +
    3163  // make one exponent fractional, thereby requiring negative overrides
    +
    3164  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    +
    3165 
    +
    3166  // catch when no negative indices are overridden
    +
    3167  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, NULL, NULL, 0), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    +
    3168 
    +
    3169  int numNegs = 1 << (numQubits-1);
    +
    3170  long long int overrideInds[numNegs];
    +
    3171  qreal overridePhases[numNegs];
    +
    3172  for (int i=0; i<numNegs; i++) {
    +
    3173  overrideInds[i] = -(i+1);
    +
    3174  overridePhases[i] = 0;
    +
    3175  }
    +
    3176 
    +
    3177  // ensure no throw when all are overriden
    +
    3178  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs) );
    +
    3179 
    +
    3180  // catch when at least one isn't overriden
    +
    3181  overrideInds[GENERATE_COPY( range(0,numNegs) )] = 0; // override a non-negative
    +
    3182  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    +
    3183  }
    +
    3184  SECTION( "negative exponent" ) {
    +
    3185 
    +
    3186  int numTerms = 3;
    +
    3187  qreal coeffs[] = {0,0,0};
    +
    3188  qreal expos[] = {1,2,3};
    +
    3189  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2 );
    +
    3190 
    +
    3191  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    +
    3192 
    +
    3193  // test both when giving no overrides, and giving all non-zero overrides
    +
    3194  int numOverrides = GENERATE( 0, 3 );
    +
    3195  long long int overrideInds[] = {1,2,3};
    +
    3196  qreal overridePhases[] = {0,0,0};
    +
    3197  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    +
    3198 
    +
    3199  // but ensure that when the zero IS overriden (anywhere), there's no error
    +
    3200  numOverrides = 3;
    +
    3201  overrideInds[GENERATE_COPY(range(0,numOverrides))] = 0;
    +
    3202  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides) );
    +
    3203  }
    +
    3204  }
    +
    3205  CLEANUP_TEST( quregVec, quregMatr );
    +
    3206 }
    +
    +

    References applyPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, qreal, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    + +
    +

    + +

    ◆ TEST_CASE() [17/124]

    + +
    +
    + + + + + + + + + + + + + + + + + + +
    TEST_CASE ("applyProjector" ,
    "" [operators] 
    )
    +
    +
    See also
    applyProjector
    +
    Author
    Tyson Jones
    + +

    Definition at line 3214 of file test_operators.cpp.

    +
    3214  {
    +
    3215 
    + + +
    3218 
    +
    3219  SECTION( "correctness" ) {
    +
    3220 
    +
    3221  int qubit = GENERATE( range(0,NUM_QUBITS) );
    +
    3222  int outcome = GENERATE( 0, 1 );
    +
    3223 
    +
    3224  // repeat these random tests 10 times on every qubit, and for both outcomes
    +
    3225  GENERATE( range(0,10) );
    +
    3226 
    +
    3227  SECTION( "state-vector" ) {
    +
    3228 
    +
    3229  SECTION( "normalised" ) {
    +
    3230 
    +
    3231  // use a random L2 state for every qubit & outcome
    + +
    3233  toQureg(vec, vecRef);
    +
    3234 
    +
    3235  // zero non-outcome reference amps
    +
    3236  for (size_t ind=0; ind<vecRef.size(); ind++) {
    +
    3237  int bit = (ind >> qubit) & 1; // target-th bit
    +
    3238  if (bit != outcome)
    +
    3239  vecRef[ind] = 0;
    +
    3240  }
    +
    3241 
    +
    3242  applyProjector(vec, qubit, outcome);
    +
    3243  REQUIRE( areEqual(vec, vecRef) );
    +
    3244  }
    +
    3245  SECTION( "unnormalised" ) {
    +
    3246 
    +
    3247  // use a random non-physical state for every qubit & outcome
    +
    3248  QVector vecRef = getRandomQVector(1 << NUM_QUBITS);
    +
    3249  toQureg(vec, vecRef);
    +
    3250 
    +
    3251  // zero non-outcome reference amps
    +
    3252  for (size_t ind=0; ind<vecRef.size(); ind++) {
    +
    3253  int bit = (ind >> qubit) & 1; // target-th bit
    +
    3254  if (bit != outcome)
    +
    3255  vecRef[ind] = 0;
    +
    3256  }
    +
    3257 
    +
    3258  applyProjector(vec, qubit, outcome);
    +
    3259  REQUIRE( areEqual(vec, vecRef) );
    +
    3260  }
    +
    3261  }
    +
    3262  SECTION( "density-matrix" ) {
    +
    3263 
    +
    3264  SECTION( "pure" ) {
    +
    3265 
    + +
    3267  QMatrix matRef = getPureDensityMatrix(vecRef);
    +
    3268 
    +
    3269  toQureg(mat, matRef);
    +
    3270  applyProjector(mat, qubit, outcome);
    +
    3271 
    +
    3272  // zero any amplitudes that aren't |outcome><outcome|
    +
    3273  for (size_t r=0; r<matRef.size(); r++) {
    +
    3274  for (size_t c=0; c<matRef.size(); c++) {
    +
    3275  int ketBit = (c >> qubit) & 1;
    +
    3276  int braBit = (r >> qubit) & 1;
    +
    3277  if (!(ketBit == outcome && braBit == outcome))
    +
    3278  matRef[r][c] = 0;
    +
    3279  }
    +
    3280  }
    +
    3281 
    +
    3282  REQUIRE( areEqual(mat, matRef) );
    +
    3283  }
    +
    3284  SECTION( "mixed" ) {
    +
    3285 
    + +
    3287 
    +
    3288  toQureg(mat, matRef);
    +
    3289  applyProjector(mat, qubit, outcome);
    +
    3290 
    +
    3291  // zero any amplitudes that aren't |outcome><outcome|
    +
    3292  for (size_t r=0; r<matRef.size(); r++) {
    +
    3293  for (size_t c=0; c<matRef.size(); c++) {
    +
    3294  int ketBit = (c >> qubit) & 1;
    +
    3295  int braBit = (r >> qubit) & 1;
    +
    3296  if (!(ketBit == outcome && braBit == outcome))
    +
    3297  matRef[r][c] = 0;
    +
    3298  }
    +
    3299  }
    +
    3300 
    +
    3301  REQUIRE( areEqual(mat, matRef) );
    +
    3302  }
    +
    3303  SECTION( "unnormalised" ) {
    +
    3304 
    +
    3305  QMatrix matRef = getRandomQMatrix(1 << NUM_QUBITS);
    +
    3306 
    +
    3307  toQureg(mat, matRef);
    +
    3308  applyProjector(mat, qubit, outcome);
    +
    3309 
    +
    3310  // zero any amplitudes that aren't |outcome><outcome|
    +
    3311  for (size_t r=0; r<matRef.size(); r++) {
    +
    3312  for (size_t c=0; c<matRef.size(); c++) {
    +
    3313  int ketBit = (c >> qubit) & 1;
    +
    3314  int braBit = (r >> qubit) & 1;
    +
    3315  if (!(ketBit == outcome && braBit == outcome))
    +
    3316  matRef[r][c] = 0;
    +
    3317  }
    +
    3318  }
    +
    3319 
    +
    3320  REQUIRE( areEqual(mat, matRef) );
    +
    3321  }
    +
    3322  }
    +
    3323  }
    +
    3324  SECTION( "input validation" ) {
    +
    3325 
    +
    3326  SECTION( "qubit index" ) {
    +
    3327 
    +
    3328  int qubit = GENERATE( -1, NUM_QUBITS );
    +
    3329  int outcome = 0;
    +
    3330  REQUIRE_THROWS_WITH( applyProjector(mat, qubit, outcome), Contains("Invalid target qubit") );
    +
    3331  }
    +
    3332  SECTION( "outcome value" ) {
    +
    3333 
    +
    3334  int qubit = 0;
    +
    3335  int outcome = GENERATE( -1, 2 );
    +
    3336  REQUIRE_THROWS_WITH( applyProjector(mat, qubit, outcome), Contains("Invalid measurement outcome") );
    +
    3337  }
    +
    3338  }
    +
    3339  destroyQureg(vec, QUEST_ENV);
    +
    3340  destroyQureg(mat, QUEST_ENV);
    +
    3341 }
    -

    References applyPhaseFuncOverrides(), applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomInt(), getRandomReal(), getTwosComplement(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, qreal, sublists(), TWOS_COMPLEMENT, and UNSIGNED.

    +

    References applyProjector(), areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getPureDensityMatrix(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [17/123]

    +

    ◆ TEST_CASE() [18/124]

    @@ -3952,158 +4120,158 @@

    See also
    applyQFT
    Author
    Tyson Jones
    -

    Definition at line 3210 of file test_operators.cpp.

    -
    3210  {
    -
    3211 
    -
    3212  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    3213 
    -
    3214  SECTION( "correctness" ) {
    -
    3215 
    -
    3216  // try every sub-register size
    -
    3217  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    -
    3218 
    -
    3219  // try every possible sub-register
    -
    3220  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    -
    3221 
    -
    3222  SECTION( "state-vector" ) {
    -
    3223 
    -
    3224  SECTION( "normalised" ) {
    -
    3225 
    - -
    3227  toQureg(quregVec, refVec);
    -
    3228 
    -
    3229  applyQFT(quregVec, qubits, numQubits);
    -
    3230  refVec = getDFT(refVec, qubits, numQubits);
    -
    3231 
    -
    3232  REQUIRE( areEqual(quregVec, refVec) );
    -
    3233  }
    -
    3234  SECTION( "unnormalised" ) {
    -
    3235 
    -
    3236  QVector refVec = getRandomQVector(1 << NUM_QUBITS);
    -
    3237  toQureg(quregVec, refVec);
    -
    3238 
    -
    3239  applyQFT(quregVec, qubits, numQubits);
    -
    3240  refVec = getDFT(refVec, qubits, numQubits);
    -
    3241 
    -
    3242  REQUIRE( areEqual(quregVec, refVec) );
    -
    3243  }
    -
    3244  }
    -
    3245  SECTION( "density-matrix" ) {
    -
    3246 
    -
    3247  SECTION( "pure" ) {
    -
    3248 
    -
    3249  /* a pure density matrix should be mapped to a pure state
    -
    3250  * corresponding to the state-vector DFT
    -
    3251  */
    -
    3252 
    -
    3253  refVec = getRandomStateVector(NUM_QUBITS);
    -
    3254  refMatr = getPureDensityMatrix(refVec);
    -
    3255  toQureg(quregMatr, refMatr);
    -
    3256 
    -
    3257  applyQFT(quregMatr, qubits, numQubits);
    -
    3258  refVec = getDFT(refVec, qubits, numQubits);
    -
    3259  refMatr = getPureDensityMatrix(refVec);
    -
    3260 
    -
    3261  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    3262  }
    -
    3263  SECTION( "mixed" ) {
    -
    3264 
    -
    3265  /* a mixed density matrix, conceptualised as a mixture of orthogonal
    -
    3266  * state-vectors, should be mapped to an equally weighted mixture
    -
    3267  * of DFTs of each state-vector (because QFT is unitary and hence
    -
    3268  * maintains state orthogonality)
    -
    3269  */
    -
    3270 
    -
    3271  int numStates = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    -
    3272  std::vector<QVector> states = getRandomOrthonormalVectors(NUM_QUBITS, numStates);
    -
    3273  std::vector<qreal> probs = getRandomProbabilities(numStates);
    -
    3274 
    -
    3275  // set qureg to random mixture of state-vectors
    -
    3276  refMatr = getMixedDensityMatrix(probs, states);
    -
    3277  toQureg(quregMatr, refMatr);
    -
    3278 
    -
    3279  // apply QFT to mixture
    -
    3280  applyQFT(quregMatr, qubits, numQubits);
    -
    3281 
    -
    3282  // compute dft of mixture, via dft of each state
    -
    3283  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    -
    3284  for (int i=0; i<numStates; i++) {
    -
    3285  QVector dft = getDFT(states[i], qubits, numQubits);
    -
    3286  refMatr += probs[i] * getPureDensityMatrix(dft);
    -
    3287  }
    -
    3288 
    -
    3289  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    3290  }
    -
    3291  SECTION( "unnormalised" ) {
    -
    3292 
    -
    3293  /* repeat method above, except that we use unnormalised vectors,
    -
    3294  * and mix them with arbitrary complex numbers instead of probabilities,
    -
    3295  * yielding an unnormalised density matrix
    -
    3296  */
    -
    3297 
    -
    3298  int numVecs = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    -
    3299  std::vector<QVector> vecs;
    -
    3300  std::vector<qcomp> coeffs;
    -
    3301  for (int i=0; i<numVecs; i++) {
    -
    3302  vecs.push_back(getRandomQVector(1 << NUM_QUBITS));
    -
    3303  coeffs.push_back(getRandomComplex());
    -
    3304  }
    -
    3305 
    -
    3306  // produce unnormalised matrix via random complex sum of random unnormalised vectors
    -
    3307  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    -
    3308  for (int i=0; i<numVecs; i++)
    -
    3309  refMatr += coeffs[i] * getPureDensityMatrix(vecs[i]);
    -
    3310 
    -
    3311  toQureg(quregMatr, refMatr);
    -
    3312  applyQFT(quregMatr, qubits, numQubits);
    -
    3313 
    -
    3314  // compute target matrix via dft of each unnormalised vector
    -
    3315  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    -
    3316  for (int i=0; i<numVecs; i++) {
    -
    3317  QVector dft = getDFT(vecs[i], qubits, numQubits);
    -
    3318  refMatr += coeffs[i] * getPureDensityMatrix(dft);
    -
    3319  }
    -
    3320 
    -
    3321  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    3322  }
    -
    3323  }
    -
    3324  }
    -
    3325  SECTION( "input validation" ) {
    -
    3326 
    -
    3327  SECTION( "number of targets" ) {
    -
    3328 
    -
    3329  // there cannot be more targets than qubits in register
    -
    3330  int numQubits = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    3331  int qubits[NUM_QUBITS+1];
    -
    3332 
    -
    3333  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid number of target"));
    -
    3334  }
    -
    3335  SECTION( "repetition in targets" ) {
    -
    3336 
    -
    3337  int numQubits = 3;
    -
    3338  int qubits[] = {1,2,2};
    -
    3339 
    -
    3340  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("target") && Contains("unique"));
    -
    3341  }
    -
    3342  SECTION( "qubit indices" ) {
    -
    3343 
    -
    3344  int numQubits = 3;
    -
    3345  int qubits[] = {1,2,3};
    -
    3346 
    -
    3347  int inv = GENERATE( -1, NUM_QUBITS );
    -
    3348  qubits[GENERATE_COPY( range(0,numQubits) )] = inv; // make invalid target
    -
    3349  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid target") );
    -
    3350  }
    -
    3351  }
    -
    3352  CLEANUP_TEST( quregVec, quregMatr );
    -
    3353 }
    +

    Definition at line 3349 of file test_operators.cpp.

    +
    3349  {
    +
    3350 
    +
    3351  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    3352 
    +
    3353  SECTION( "correctness" ) {
    +
    3354 
    +
    3355  // try every sub-register size
    +
    3356  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    +
    3357 
    +
    3358  // try every possible sub-register
    +
    3359  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    +
    3360 
    +
    3361  SECTION( "state-vector" ) {
    +
    3362 
    +
    3363  SECTION( "normalised" ) {
    +
    3364 
    + +
    3366  toQureg(quregVec, refVec);
    +
    3367 
    +
    3368  applyQFT(quregVec, qubits, numQubits);
    +
    3369  refVec = getDFT(refVec, qubits, numQubits);
    +
    3370 
    +
    3371  REQUIRE( areEqual(quregVec, refVec) );
    +
    3372  }
    +
    3373  SECTION( "unnormalised" ) {
    +
    3374 
    +
    3375  QVector refVec = getRandomQVector(1 << NUM_QUBITS);
    +
    3376  toQureg(quregVec, refVec);
    +
    3377 
    +
    3378  applyQFT(quregVec, qubits, numQubits);
    +
    3379  refVec = getDFT(refVec, qubits, numQubits);
    +
    3380 
    +
    3381  REQUIRE( areEqual(quregVec, refVec) );
    +
    3382  }
    +
    3383  }
    +
    3384  SECTION( "density-matrix" ) {
    +
    3385 
    +
    3386  SECTION( "pure" ) {
    +
    3387 
    +
    3388  /* a pure density matrix should be mapped to a pure state
    +
    3389  * corresponding to the state-vector DFT
    +
    3390  */
    +
    3391 
    +
    3392  refVec = getRandomStateVector(NUM_QUBITS);
    +
    3393  refMatr = getPureDensityMatrix(refVec);
    +
    3394  toQureg(quregMatr, refMatr);
    +
    3395 
    +
    3396  applyQFT(quregMatr, qubits, numQubits);
    +
    3397  refVec = getDFT(refVec, qubits, numQubits);
    +
    3398  refMatr = getPureDensityMatrix(refVec);
    +
    3399 
    +
    3400  REQUIRE( areEqual(quregMatr, refMatr) );
    +
    3401  }
    +
    3402  SECTION( "mixed" ) {
    +
    3403 
    +
    3404  /* a mixed density matrix, conceptualised as a mixture of orthogonal
    +
    3405  * state-vectors, should be mapped to an equally weighted mixture
    +
    3406  * of DFTs of each state-vector (because QFT is unitary and hence
    +
    3407  * maintains state orthogonality)
    +
    3408  */
    +
    3409 
    +
    3410  int numStates = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    +
    3411  std::vector<QVector> states = getRandomOrthonormalVectors(NUM_QUBITS, numStates);
    +
    3412  std::vector<qreal> probs = getRandomProbabilities(numStates);
    +
    3413 
    +
    3414  // set qureg to random mixture of state-vectors
    +
    3415  refMatr = getMixedDensityMatrix(probs, states);
    +
    3416  toQureg(quregMatr, refMatr);
    +
    3417 
    +
    3418  // apply QFT to mixture
    +
    3419  applyQFT(quregMatr, qubits, numQubits);
    +
    3420 
    +
    3421  // compute dft of mixture, via dft of each state
    +
    3422  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    +
    3423  for (int i=0; i<numStates; i++) {
    +
    3424  QVector dft = getDFT(states[i], qubits, numQubits);
    +
    3425  refMatr += probs[i] * getPureDensityMatrix(dft);
    +
    3426  }
    +
    3427 
    +
    3428  REQUIRE( areEqual(quregMatr, refMatr) );
    +
    3429  }
    +
    3430  SECTION( "unnormalised" ) {
    +
    3431 
    +
    3432  /* repeat method above, except that we use unnormalised vectors,
    +
    3433  * and mix them with arbitrary complex numbers instead of probabilities,
    +
    3434  * yielding an unnormalised density matrix
    +
    3435  */
    +
    3436 
    +
    3437  int numVecs = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    +
    3438  std::vector<QVector> vecs;
    +
    3439  std::vector<qcomp> coeffs;
    +
    3440  for (int i=0; i<numVecs; i++) {
    +
    3441  vecs.push_back(getRandomQVector(1 << NUM_QUBITS));
    +
    3442  coeffs.push_back(getRandomComplex());
    +
    3443  }
    +
    3444 
    +
    3445  // produce unnormalised matrix via random complex sum of random unnormalised vectors
    +
    3446  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    +
    3447  for (int i=0; i<numVecs; i++)
    +
    3448  refMatr += coeffs[i] * getPureDensityMatrix(vecs[i]);
    +
    3449 
    +
    3450  toQureg(quregMatr, refMatr);
    +
    3451  applyQFT(quregMatr, qubits, numQubits);
    +
    3452 
    +
    3453  // compute target matrix via dft of each unnormalised vector
    +
    3454  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    +
    3455  for (int i=0; i<numVecs; i++) {
    +
    3456  QVector dft = getDFT(vecs[i], qubits, numQubits);
    +
    3457  refMatr += coeffs[i] * getPureDensityMatrix(dft);
    +
    3458  }
    +
    3459 
    +
    3460  REQUIRE( areEqual(quregMatr, refMatr) );
    +
    3461  }
    +
    3462  }
    +
    3463  }
    +
    3464  SECTION( "input validation" ) {
    +
    3465 
    +
    3466  SECTION( "number of targets" ) {
    +
    3467 
    +
    3468  // there cannot be more targets than qubits in register
    +
    3469  int numQubits = GENERATE( -1, 0, NUM_QUBITS+1 );
    +
    3470  int qubits[NUM_QUBITS+1];
    +
    3471 
    +
    3472  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid number of target"));
    +
    3473  }
    +
    3474  SECTION( "repetition in targets" ) {
    +
    3475 
    +
    3476  int numQubits = 3;
    +
    3477  int qubits[] = {1,2,2};
    +
    3478 
    +
    3479  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("target") && Contains("unique"));
    +
    3480  }
    +
    3481  SECTION( "qubit indices" ) {
    +
    3482 
    +
    3483  int numQubits = 3;
    +
    3484  int qubits[] = {1,2,3};
    +
    3485 
    +
    3486  int inv = GENERATE( -1, NUM_QUBITS );
    +
    3487  qubits[GENERATE_COPY( range(0,numQubits) )] = inv; // make invalid target
    +
    3488  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid target") );
    +
    3489  }
    +
    3490  }
    +
    3491  CLEANUP_TEST( quregVec, quregMatr );
    +
    3492 }
    -

    References applyQFT(), areEqual(), CLEANUP_TEST, getDFT(), getMixedDensityMatrix(), getPureDensityMatrix(), getRandomComplex(), getRandomOrthonormalVectors(), getRandomProbabilities(), getRandomQVector(), getRandomStateVector(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, sublists(), and toQureg().

    +

    References applyQFT(), areEqual(), CLEANUP_TEST, getDFT(), getMixedDensityMatrix(), getPureDensityMatrix(), getRandomComplex(), getRandomOrthonormalVectors(), getRandomProbabilities(), getRandomQVector(), getRandomStateVector(), getZeroMatrix(), NUM_QUBITS, PREPARE_TEST, sublists(), and toQureg().

    -

    ◆ TEST_CASE() [18/123]

    +

    ◆ TEST_CASE() [19/124]

    @@ -4130,240 +4298,240 @@

    See also
    applyTrotterCircuit
    Author
    Tyson Jones
    -

    Definition at line 3361 of file test_operators.cpp.

    -
    3361  {
    -
    3362 
    - - -
    3365  initDebugState(vec);
    -
    3366  initDebugState(mat);
    -
    3367 
    -
    3368  Qureg vecRef = createCloneQureg(vec, QUEST_ENV);
    -
    3369  Qureg matRef = createCloneQureg(mat, QUEST_ENV);
    -
    3370 
    -
    3371  SECTION( "correctness" ) {
    -
    3372 
    -
    3373  SECTION( "one term" ) {
    -
    3374 
    -
    3375  // a Hamiltonian with one term has an exact (trivial) Trotterisation
    - -
    3377 
    -
    3378  // H = coeff X Y Z (on qubits 0,1,2)
    -
    3379  qreal coeff = getRandomReal(-5, 5);
    -
    3380  int numTargs = 3;
    -
    3381  int targs[] = {0, 1, 2};
    -
    3382  pauliOpType codes[] = {PAULI_X, PAULI_Y, PAULI_Z};
    -
    3383  hamil.termCoeffs[0] = coeff;
    -
    3384  for (int i=0; i<numTargs; i++)
    -
    3385  hamil.pauliCodes[targs[i]] = codes[i];
    -
    3386 
    -
    3387  // time can be negative
    -
    3388  qreal time = getRandomReal(-2,2);
    -
    3389 
    -
    3390  // by commutation, all reps & orders yield the same total unitary
    -
    3391  int reps = GENERATE( range(1,5) );
    -
    3392 
    -
    3393  // applyTrotter(t, 1, 1) = exp(-i t coeff paulis)
    -
    3394  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    -
    3395 
    -
    3396  SECTION( "state-vector" ) {
    -
    3397 
    -
    3398  int order = GENERATE( 1, 2, 4 );
    -
    3399 
    -
    3400  applyTrotterCircuit(vec, hamil, time, order, reps);
    -
    3401  multiRotatePauli(vecRef, targs, codes, numTargs, 2*time*coeff);
    -
    3402  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    -
    3403  }
    -
    3404  SECTION( "density-matrix" ) {
    -
    3405 
    -
    3406  int order = GENERATE( 1, 2 ); // precision bites density-matrices quickly
    -
    3407 
    -
    3408  applyTrotterCircuit(mat, hamil, time, order, reps);
    -
    3409  multiRotatePauli(matRef, targs, codes, numTargs, 2*time*coeff);
    -
    3410  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    -
    3411  }
    -
    3412 
    -
    3413  destroyPauliHamil(hamil);
    -
    3414  }
    -
    3415  SECTION( "commuting terms" ) {
    -
    3416 
    -
    3417  // a Hamiltonian of commuting terms, Trotterises exactly
    - -
    3419 
    -
    3420  // H = c0 X Y I + c1 X I Z (on qubits 0,1,2)
    -
    3421  int targs[] = {0, 1, 2};
    -
    3422  hamil.pauliCodes[0] = PAULI_X;
    -
    3423  hamil.pauliCodes[0 + NUM_QUBITS] = PAULI_X;
    -
    3424  hamil.pauliCodes[1] = PAULI_Y;
    -
    3425  hamil.pauliCodes[1 + NUM_QUBITS] = PAULI_I;
    -
    3426  hamil.pauliCodes[2] = PAULI_I;
    -
    3427  hamil.pauliCodes[2 + NUM_QUBITS] = PAULI_Z;
    -
    3428  for (int i=0; i<hamil.numSumTerms; i++)
    -
    3429  hamil.termCoeffs[i] = getRandomReal(-5,5);
    -
    3430 
    -
    3431  // time can be negative
    -
    3432  qreal time = getRandomReal(-2,2);
    -
    3433 
    -
    3434  // applyTrotter(t, 1, 1) = exp(-i t c0 paulis0) exp(-i t c1 paulis1)
    -
    3435  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    -
    3436 
    -
    3437  SECTION( "state-vector" ) {
    -
    3438 
    -
    3439  int reps = GENERATE( range(1,5) );
    -
    3440  int order = GENERATE( 1, 2, 4 );
    -
    3441 
    -
    3442  applyTrotterCircuit(vec, hamil, time, order, reps);
    -
    3443  multiRotatePauli(vecRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    -
    3444  multiRotatePauli(vecRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    -
    3445  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    -
    3446  }
    -
    3447  SECTION( "density-matrix" ) {
    -
    3448 
    -
    3449  int reps = GENERATE( range(1,5) );
    -
    3450  int order = GENERATE( 1, 2 ); // precision hurts density matrices quickly
    -
    3451 
    -
    3452  applyTrotterCircuit(mat, hamil, time, order, reps);
    -
    3453  multiRotatePauli(matRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    -
    3454  multiRotatePauli(matRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    -
    3455  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    -
    3456  }
    -
    3457 
    -
    3458  destroyPauliHamil(hamil);
    -
    3459  }
    -
    3460  SECTION( "general" ) {
    -
    3461 
    -
    3462  /* We'll consider an analytic time-evolved state, so that we can avoid
    -
    3463  * comparing applyTrotterCircuit to other numerical approximations.
    -
    3464  * We can construct such a state, by using a Hamiltonian with known
    -
    3465  * analytic eigenvalues, and hence a known period. Time evolution of the
    -
    3466  * period will just yield the input state.
    -
    3467  *
    -
    3468  * E.g. H = pi sqrt(2) X Y Z X Y + pi Y Z X Y Z + pi Z X Y Z X
    -
    3469  * has (degenerate) eigenvalues +- 2 pi, so the period
    -
    3470  * of the Hamiltonian is t=1.
    -
    3471  */
    -
    3472 
    -
    3473  // hardcoded 5 qubits here in the Pauli codes
    -
    3474  REQUIRE( NUM_QUBITS == 5 );
    -
    3475 
    - -
    3477  qreal coeffs[] = {(qreal) (M_PI * sqrt(2.0)), M_PI, M_PI};
    -
    3478  enum pauliOpType codes[] = {
    - - - -
    3482  initPauliHamil(hamil, coeffs, codes);
    -
    3483 
    -
    3484  // evolving to t=1 should leave the input state unchanged
    -
    3485  qreal time = 1;
    -
    3486 
    -
    3487  // since unnormalised (initDebugState), max fid is 728359.8336
    -
    3488  qreal fidNorm = 728359.8336;
    -
    3489 
    -
    3490  SECTION( "absolute" ) {
    -
    3491 
    -
    3492  // such a high order and reps should yield precise solution
    -
    3493  int order = 4;
    -
    3494  int reps = 20;
    -
    3495  applyTrotterCircuit(vec, hamil, time, 4, 20);
    -
    3496  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    3497 
    -
    3498  REQUIRE( fid == Approx(1).epsilon(1E-8) );
    -
    3499  }
    -
    3500  SECTION( "repetitions scaling" ) {
    -
    3501 
    -
    3502  // exclude order 1; too few reps for monotonic increase of accuracy
    -
    3503  int order = GENERATE( 2, 4, 6 );
    -
    3504 
    -
    3505  // accuracy should increase with increasing repetitions
    -
    3506  int reps[] = {1, 5, 10};
    -
    3507 
    -
    3508  qreal prevFid = 0;
    -
    3509  for (int i=0; i<3; i++) {
    -
    3510  initDebugState(vec);
    -
    3511  applyTrotterCircuit(vec, hamil, time, order, reps[i]);
    -
    3512  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    3513 
    -
    3514  REQUIRE( fid >= prevFid );
    -
    3515  prevFid = fid;
    -
    3516  }
    -
    3517  }
    -
    3518  SECTION( "order scaling" ) {
    -
    3519 
    -
    3520  // exclude order 1; too few reps for monotonic increase of accuracy
    -
    3521  int reps = GENERATE( 5, 10 );
    -
    3522 
    -
    3523  // accuracy should increase with increasing repetitions
    -
    3524  int orders[] = {1, 2, 4, 6};
    +

    Definition at line 3500 of file test_operators.cpp.

    +
    3500  {
    +
    3501 
    + + +
    3504  initDebugState(vec);
    +
    3505  initDebugState(mat);
    +
    3506 
    +
    3507  Qureg vecRef = createCloneQureg(vec, QUEST_ENV);
    +
    3508  Qureg matRef = createCloneQureg(mat, QUEST_ENV);
    +
    3509 
    +
    3510  SECTION( "correctness" ) {
    +
    3511 
    +
    3512  SECTION( "one term" ) {
    +
    3513 
    +
    3514  // a Hamiltonian with one term has an exact (trivial) Trotterisation
    + +
    3516 
    +
    3517  // H = coeff X Y Z (on qubits 0,1,2)
    +
    3518  qreal coeff = getRandomReal(-5, 5);
    +
    3519  int numTargs = 3;
    +
    3520  int targs[] = {0, 1, 2};
    +
    3521  pauliOpType codes[] = {PAULI_X, PAULI_Y, PAULI_Z};
    +
    3522  hamil.termCoeffs[0] = coeff;
    +
    3523  for (int i=0; i<numTargs; i++)
    +
    3524  hamil.pauliCodes[targs[i]] = codes[i];
    3525 
    -
    3526  qreal prevFid = 0;
    -
    3527  for (int i=0; i<4; i++) {
    -
    3528  initDebugState(vec);
    -
    3529  applyTrotterCircuit(vec, hamil, time, orders[i], reps);
    -
    3530  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    3531 
    -
    3532  REQUIRE( fid >= prevFid );
    -
    3533  prevFid = fid;
    -
    3534  }
    -
    3535  }
    -
    3536 
    -
    3537  destroyPauliHamil(hamil);
    -
    3538  }
    -
    3539  }
    -
    3540  SECTION( "input validation" ) {
    -
    3541 
    -
    3542  SECTION( "repetitions" ) {
    -
    3543 
    - -
    3545  int reps = GENERATE( -1, 0 );
    -
    3546 
    -
    3547  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, reps), Contains("repetitions must be >=1") );
    -
    3548 
    -
    3549  destroyPauliHamil(hamil);
    -
    3550  }
    -
    3551  SECTION( "order" ) {
    -
    3552 
    - -
    3554  int order = GENERATE( -1, 0, 3, 5, 7 );
    +
    3526  // time can be negative
    +
    3527  qreal time = getRandomReal(-2,2);
    +
    3528 
    +
    3529  // by commutation, all reps & orders yield the same total unitary
    +
    3530  int reps = GENERATE( range(1,5) );
    +
    3531 
    +
    3532  // applyTrotter(t, 1, 1) = exp(-i t coeff paulis)
    +
    3533  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    +
    3534 
    +
    3535  SECTION( "state-vector" ) {
    +
    3536 
    +
    3537  int order = GENERATE( 1, 2, 4 );
    +
    3538 
    +
    3539  applyTrotterCircuit(vec, hamil, time, order, reps);
    +
    3540  multiRotatePauli(vecRef, targs, codes, numTargs, 2*time*coeff);
    +
    3541  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    +
    3542  }
    +
    3543  SECTION( "density-matrix" ) {
    +
    3544 
    +
    3545  int order = GENERATE( 1, 2 ); // precision bites density-matrices quickly
    +
    3546 
    +
    3547  applyTrotterCircuit(mat, hamil, time, order, reps);
    +
    3548  multiRotatePauli(matRef, targs, codes, numTargs, 2*time*coeff);
    +
    3549  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    +
    3550  }
    +
    3551 
    +
    3552  destroyPauliHamil(hamil);
    +
    3553  }
    +
    3554  SECTION( "commuting terms" ) {
    3555 
    -
    3556  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, order, 1), Contains("order must be 1, or an even number") );
    -
    3557 
    -
    3558  destroyPauliHamil(hamil);
    -
    3559  }
    -
    3560  SECTION( "pauli codes" ) {
    -
    3561 
    -
    3562  int numTerms = 3;
    -
    3563  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    3564 
    -
    3565  // make one pauli code wrong
    -
    3566  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    3567  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("Invalid Pauli code") );
    -
    3568 
    -
    3569  destroyPauliHamil(hamil);
    -
    3570  }
    -
    3571  SECTION( "matching hamiltonian qubits" ) {
    +
    3556  // a Hamiltonian of commuting terms, Trotterises exactly
    + +
    3558 
    +
    3559  // H = c0 X Y I + c1 X I Z (on qubits 0,1,2)
    +
    3560  int targs[] = {0, 1, 2};
    +
    3561  hamil.pauliCodes[0] = PAULI_X;
    +
    3562  hamil.pauliCodes[0 + NUM_QUBITS] = PAULI_X;
    +
    3563  hamil.pauliCodes[1] = PAULI_Y;
    +
    3564  hamil.pauliCodes[1 + NUM_QUBITS] = PAULI_I;
    +
    3565  hamil.pauliCodes[2] = PAULI_I;
    +
    3566  hamil.pauliCodes[2 + NUM_QUBITS] = PAULI_Z;
    +
    3567  for (int i=0; i<hamil.numSumTerms; i++)
    +
    3568  hamil.termCoeffs[i] = getRandomReal(-5,5);
    +
    3569 
    +
    3570  // time can be negative
    +
    3571  qreal time = getRandomReal(-2,2);
    3572 
    -
    3573  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    -
    3574 
    -
    3575  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("same number of qubits") );
    -
    3576  REQUIRE_THROWS_WITH( applyTrotterCircuit(mat, hamil, 1, 1, 1), Contains("same number of qubits") );
    -
    3577 
    -
    3578  destroyPauliHamil(hamil);
    -
    3579  }
    -
    3580  }
    -
    3581 
    -
    3582  destroyQureg(vec, QUEST_ENV);
    -
    3583  destroyQureg(mat, QUEST_ENV);
    -
    3584  destroyQureg(vecRef, QUEST_ENV);
    -
    3585  destroyQureg(matRef, QUEST_ENV);
    -
    3586 }
    +
    3573  // applyTrotter(t, 1, 1) = exp(-i t c0 paulis0) exp(-i t c1 paulis1)
    +
    3574  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    +
    3575 
    +
    3576  SECTION( "state-vector" ) {
    +
    3577 
    +
    3578  int reps = GENERATE( range(1,5) );
    +
    3579  int order = GENERATE( 1, 2, 4 );
    +
    3580 
    +
    3581  applyTrotterCircuit(vec, hamil, time, order, reps);
    +
    3582  multiRotatePauli(vecRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    +
    3583  multiRotatePauli(vecRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    +
    3584  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    +
    3585  }
    +
    3586  SECTION( "density-matrix" ) {
    +
    3587 
    +
    3588  int reps = GENERATE( range(1,5) );
    +
    3589  int order = GENERATE( 1, 2 ); // precision hurts density matrices quickly
    +
    3590 
    +
    3591  applyTrotterCircuit(mat, hamil, time, order, reps);
    +
    3592  multiRotatePauli(matRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    +
    3593  multiRotatePauli(matRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    +
    3594  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    +
    3595  }
    +
    3596 
    +
    3597  destroyPauliHamil(hamil);
    +
    3598  }
    +
    3599  SECTION( "general" ) {
    +
    3600 
    +
    3601  /* We'll consider an analytic time-evolved state, so that we can avoid
    +
    3602  * comparing applyTrotterCircuit to other numerical approximations.
    +
    3603  * We can construct such a state, by using a Hamiltonian with known
    +
    3604  * analytic eigenvalues, and hence a known period. Time evolution of the
    +
    3605  * period will just yield the input state.
    +
    3606  *
    +
    3607  * E.g. H = pi sqrt(2) X Y Z X Y + pi Y Z X Y Z + pi Z X Y Z X
    +
    3608  * has (degenerate) eigenvalues +- 2 pi, so the period
    +
    3609  * of the Hamiltonian is t=1.
    +
    3610  */
    +
    3611 
    +
    3612  // hardcoded 5 qubits here in the Pauli codes
    +
    3613  REQUIRE( NUM_QUBITS == 5 );
    +
    3614 
    + +
    3616  qreal coeffs[] = {(qreal) (M_PI * sqrt(2.0)), M_PI, M_PI};
    +
    3617  enum pauliOpType codes[] = {
    + + + +
    3621  initPauliHamil(hamil, coeffs, codes);
    +
    3622 
    +
    3623  // evolving to t=1 should leave the input state unchanged
    +
    3624  qreal time = 1;
    +
    3625 
    +
    3626  // since unnormalised (initDebugState), max fid is 728359.8336
    +
    3627  qreal fidNorm = 728359.8336;
    +
    3628 
    +
    3629  SECTION( "absolute" ) {
    +
    3630 
    +
    3631  // such a high order and reps should yield precise solution
    +
    3632  int order = 4;
    +
    3633  int reps = 20;
    +
    3634  applyTrotterCircuit(vec, hamil, time, 4, 20);
    +
    3635  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    +
    3636 
    +
    3637  REQUIRE( fid == Approx(1).epsilon(1E-8) );
    +
    3638  }
    +
    3639  SECTION( "repetitions scaling" ) {
    +
    3640 
    +
    3641  // exclude order 1; too few reps for monotonic increase of accuracy
    +
    3642  int order = GENERATE( 2, 4, 6 );
    +
    3643 
    +
    3644  // accuracy should increase with increasing repetitions
    +
    3645  int reps[] = {1, 5, 10};
    +
    3646 
    +
    3647  qreal prevFid = 0;
    +
    3648  for (int i=0; i<3; i++) {
    +
    3649  initDebugState(vec);
    +
    3650  applyTrotterCircuit(vec, hamil, time, order, reps[i]);
    +
    3651  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    +
    3652 
    +
    3653  REQUIRE( fid >= prevFid );
    +
    3654  prevFid = fid;
    +
    3655  }
    +
    3656  }
    +
    3657  SECTION( "order scaling" ) {
    +
    3658 
    +
    3659  // exclude order 1; too few reps for monotonic increase of accuracy
    +
    3660  int reps = GENERATE( 5, 10 );
    +
    3661 
    +
    3662  // accuracy should increase with increasing repetitions
    +
    3663  int orders[] = {1, 2, 4, 6};
    +
    3664 
    +
    3665  qreal prevFid = 0;
    +
    3666  for (int i=0; i<4; i++) {
    +
    3667  initDebugState(vec);
    +
    3668  applyTrotterCircuit(vec, hamil, time, orders[i], reps);
    +
    3669  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    +
    3670 
    +
    3671  REQUIRE( fid >= prevFid );
    +
    3672  prevFid = fid;
    +
    3673  }
    +
    3674  }
    +
    3675 
    +
    3676  destroyPauliHamil(hamil);
    +
    3677  }
    +
    3678  }
    +
    3679  SECTION( "input validation" ) {
    +
    3680 
    +
    3681  SECTION( "repetitions" ) {
    +
    3682 
    + +
    3684  int reps = GENERATE( -1, 0 );
    +
    3685 
    +
    3686  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, reps), Contains("repetitions must be >=1") );
    +
    3687 
    +
    3688  destroyPauliHamil(hamil);
    +
    3689  }
    +
    3690  SECTION( "order" ) {
    +
    3691 
    + +
    3693  int order = GENERATE( -1, 0, 3, 5, 7 );
    +
    3694 
    +
    3695  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, order, 1), Contains("order must be 1, or an even number") );
    +
    3696 
    +
    3697  destroyPauliHamil(hamil);
    +
    3698  }
    +
    3699  SECTION( "pauli codes" ) {
    +
    3700 
    +
    3701  int numTerms = 3;
    +
    3702  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    +
    3703 
    +
    3704  // make one pauli code wrong
    +
    3705  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    +
    3706  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("Invalid Pauli code") );
    +
    3707 
    +
    3708  destroyPauliHamil(hamil);
    +
    3709  }
    +
    3710  SECTION( "matching hamiltonian qubits" ) {
    +
    3711 
    +
    3712  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    +
    3713 
    +
    3714  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("same number of qubits") );
    +
    3715  REQUIRE_THROWS_WITH( applyTrotterCircuit(mat, hamil, 1, 1, 1), Contains("same number of qubits") );
    +
    3716 
    +
    3717  destroyPauliHamil(hamil);
    +
    3718  }
    +
    3719  }
    +
    3720 
    +
    3721  destroyQureg(vec, QUEST_ENV);
    +
    3722  destroyQureg(mat, QUEST_ENV);
    +
    3723  destroyQureg(vecRef, QUEST_ENV);
    +
    3724  destroyQureg(matRef, QUEST_ENV);
    +
    3725 }
    -

    References applyTrotterCircuit(), areEqual(), calcFidelity(), createCloneQureg(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), getRandomReal(), initDebugState(), initPauliHamil(), M_PI, multiRotatePauli(), NUM_QUBITS, PauliHamil::numSumTerms, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qreal, QUEST_ENV, and PauliHamil::termCoeffs.

    +

    References applyTrotterCircuit(), areEqual(), calcFidelity(), createCloneQureg(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), getRandomReal(), initDebugState(), initPauliHamil(), M_PI, multiRotatePauli(), NUM_QUBITS, PauliHamil::numSumTerms, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qreal, QUEST_ENV, and PauliHamil::termCoeffs.

    -

    ◆ TEST_CASE() [19/123]

    +

    ◆ TEST_CASE() [20/124]

    @@ -4481,12 +4649,12 @@

    108  destroyQureg(mat2, QUEST_ENV);

    109 }
    -

    References calcDensityInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    +

    References calcDensityInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [20/123]

    +

    ◆ TEST_CASE() [21/124]

    @@ -4580,12 +4748,12 @@

    180  destroyQureg(mat, QUEST_ENV);

    181 }
    -

    References calcExpecDiagonalOp(), createDensityQureg(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), getRandomReal(), Complex::imag, DiagonalOp::imag, initDebugState(), NUM_QUBITS, DiagonalOp::numElemsPerChunk, qcomp, QUEST_ENV, Complex::real, DiagonalOp::real, syncDiagonalOp(), toQMatrix(), and toQVector().

    +

    References calcExpecDiagonalOp(), createDensityQureg(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), getRandomReal(), Complex::imag, DiagonalOp::imag, initDebugState(), NUM_QUBITS, DiagonalOp::numElemsPerChunk, qcomp, QUEST_ENV, Complex::real, DiagonalOp::real, syncDiagonalOp(), toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [21/123]

    +

    ◆ TEST_CASE() [22/124]

    @@ -4720,12 +4888,12 @@

    293  destroyQureg(matWork, QUEST_ENV);

    294 }
    -

    References calcExpecPauliHamil(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), initDebugState(), NUM_QUBITS, PauliHamil::pauliCodes, qcomp, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    +

    References calcExpecPauliHamil(), createDensityQureg(), createPauliHamil(), createQureg(), destroyPauliHamil(), destroyQureg(), initDebugState(), NUM_QUBITS, PauliHamil::pauliCodes, qcomp, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [22/123]

    +

    ◆ TEST_CASE() [23/124]

    @@ -4889,12 +5057,12 @@

    435  destroyQureg(matWork, QUEST_ENV);

    436 }
    -

    References applyReferenceOp(), calcExpecPauliProd(), createDensityQureg(), createQureg(), destroyQureg(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomInt(), initDebugState(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, qcomp, qreal, QUEST_ENV, sublists(), toQMatrix(), and toQVector().

    +

    References applyReferenceOp(), calcExpecPauliProd(), createDensityQureg(), createQureg(), destroyQureg(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomInt(), initDebugState(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, qcomp, qreal, QUEST_ENV, sublists(), toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [23/123]

    +

    ◆ TEST_CASE() [24/124]

    @@ -5032,12 +5200,12 @@

    551  destroyQureg(matWork, QUEST_ENV);

    552 }
    -

    References calcExpecPauliSum(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), NUM_QUBITS, PAULI_I, qcomp, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    +

    References calcExpecPauliSum(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), NUM_QUBITS, PAULI_I, qcomp, qreal, QUEST_ENV, setRandomPauliSum(), toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [24/123]

    +

    ◆ TEST_CASE() [25/124]

    @@ -5211,12 +5379,12 @@

    703  destroyQureg(pure, QUEST_ENV);

    704 }
    -

    References calcFidelity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, and toQureg().

    +

    References calcFidelity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [25/123]

    +

    ◆ TEST_CASE() [26/124]

    @@ -5334,12 +5502,12 @@

    799  destroyQureg(mat2, QUEST_ENV);

    800 }
    -

    References calcHilbertSchmidtDistance(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    +

    References calcHilbertSchmidtDistance(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [26/123]

    +

    ◆ TEST_CASE() [27/124]

    @@ -5436,12 +5604,12 @@

    874  destroyQureg(vec2, QUEST_ENV);

    875 }
    -

    References calcInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getRandomQVector(), getRandomStateVector(), Complex::imag, NUM_QUBITS, qcomp, QUEST_ENV, Complex::real, and toQureg().

    +

    References calcInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getRandomQVector(), getRandomStateVector(), Complex::imag, NUM_QUBITS, qcomp, QUEST_ENV, Complex::real, and toQureg().

    -

    ◆ TEST_CASE() [27/123]

    +

    ◆ TEST_CASE() [28/124]

    @@ -5589,12 +5757,12 @@

    1000  destroyQureg(mat, QUEST_ENV);

    1001 }
    -

    References areEqual(), calcProbOfAllOutcomes(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, qreal, QUEST_ENV, sublists(), and toQureg().

    +

    References areEqual(), calcProbOfAllOutcomes(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, qreal, QUEST_ENV, sublists(), and toQureg().

    -

    ◆ TEST_CASE() [28/123]

    +

    ◆ TEST_CASE() [29/124]

    @@ -5739,12 +5907,12 @@

    1124  destroyQureg(mat, QUEST_ENV);

    1125 }
    -

    References calcProbOfOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    +

    References calcProbOfOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [29/123]

    +

    ◆ TEST_CASE() [30/124]

    @@ -5838,12 +6006,12 @@

    1196  destroyQureg(mat, QUEST_ENV);

    1197 }
    -

    References calcPurity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), initZeroState(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    +

    References calcPurity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), initZeroState(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [30/123]

    +

    ◆ TEST_CASE() [31/124]

    @@ -5932,12 +6100,12 @@

    1263  destroyQureg(mat, QUEST_ENV);

    1264 }
    -

    References calcTotalProb(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initBlankState(), initDebugState(), initPlusState(), NUM_QUBITS, qreal, QUEST_ENV, toQMatrix(), toQureg(), and toQVector().

    +

    References calcTotalProb(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initBlankState(), initDebugState(), initPlusState(), NUM_QUBITS, qreal, QUEST_ENV, toQMatrix(), toQureg(), and toQVector().

    -

    ◆ TEST_CASE() [31/123]

    +

    ◆ TEST_CASE() [32/124]

    @@ -6034,12 +6202,12 @@

    81  destroyQureg(mat1, QUEST_ENV);

    82 }
    -

    References areEqual(), cloneQureg(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initDebugState(), NUM_QUBITS, Qureg::numQubitsRepresented, QUEST_ENV, toQMatrix(), and toQVector().

    +

    References areEqual(), cloneQureg(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initDebugState(), NUM_QUBITS, Qureg::numQubitsRepresented, QUEST_ENV, toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [32/123]

    +

    ◆ TEST_CASE() [33/124]

    @@ -6167,12 +6335,12 @@

    112  destroyQureg(mat, QUEST_ENV);

    113 }
    -

    References areEqual(), collapseToOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initClassicalState(), initZeroState(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    +

    References areEqual(), collapseToOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initClassicalState(), initZeroState(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [33/123]

    +

    ◆ TEST_CASE() [34/124]

    @@ -6245,12 +6413,12 @@

    88  CLEANUP_TEST( quregVec, quregMatr );

    89 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, compactUnitary(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, compactUnitary(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

    -

    ◆ TEST_CASE() [34/123]

    +

    ◆ TEST_CASE() [35/124]

    @@ -6330,12 +6498,12 @@

    146  CLEANUP_TEST( quregVec, quregMatr );

    147 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledCompactUnitary(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledCompactUnitary(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

    -

    ◆ TEST_CASE() [35/123]

    +

    ◆ TEST_CASE() [36/124]

    @@ -6497,12 +6665,12 @@

    286  CLEANUP_TEST( quregVec, quregMatr );

    287 }
    -

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, controlledMultiQubitUnitary(), createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    +

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, controlledMultiQubitUnitary(), createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    -

    ◆ TEST_CASE() [36/123]

    +

    ◆ TEST_CASE() [37/124]

    @@ -6570,12 +6738,12 @@

    332  CLEANUP_TEST( quregVec, quregMatr );

    333 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledNot(), NUM_QUBITS, and PREPARE_TEST.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledNot(), NUM_QUBITS, and PREPARE_TEST.

    -

    ◆ TEST_CASE() [37/123]

    +

    ◆ TEST_CASE() [38/124]

    @@ -6643,12 +6811,12 @@

    378  CLEANUP_TEST( quregVec, quregMatr );

    379 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPauliY(), NUM_QUBITS, PREPARE_TEST, and qcomp.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPauliY(), NUM_QUBITS, PREPARE_TEST, and qcomp.

    -

    ◆ TEST_CASE() [38/123]

    +

    ◆ TEST_CASE() [39/124]

    @@ -6716,12 +6884,12 @@

    424  CLEANUP_TEST( quregVec, quregMatr );

    425 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseFlip(), NUM_QUBITS, and PREPARE_TEST.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseFlip(), NUM_QUBITS, and PREPARE_TEST.

    -

    ◆ TEST_CASE() [39/123]

    +

    ◆ TEST_CASE() [40/124]

    @@ -6790,12 +6958,12 @@

    471  CLEANUP_TEST( quregVec, quregMatr );

    472 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseShift(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, and qreal.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseShift(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, and qreal.

    -

    ◆ TEST_CASE() [40/123]

    +

    ◆ TEST_CASE() [41/124]

    @@ -6879,12 +7047,12 @@

    533  CLEANUP_TEST( quregVec, quregMatr );

    534 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateAroundAxis(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, qreal, Vector::x, Vector::y, and Vector::z.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateAroundAxis(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, qreal, Vector::x, Vector::y, and Vector::z.

    -

    ◆ TEST_CASE() [41/123]

    +

    ◆ TEST_CASE() [42/124]

    @@ -6955,12 +7123,12 @@

    582  CLEANUP_TEST( quregVec, quregMatr );

    583 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateX(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, and qreal.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateX(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, and qreal.

    -

    ◆ TEST_CASE() [42/123]

    +

    ◆ TEST_CASE() [43/124]

    @@ -7029,12 +7197,12 @@

    629  CLEANUP_TEST( quregVec, quregMatr );

    630 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateY(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, and qreal.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateY(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, and qreal.

    -

    ◆ TEST_CASE() [43/123]

    +

    ◆ TEST_CASE() [44/124]

    @@ -7103,12 +7271,12 @@

    676  CLEANUP_TEST( quregVec, quregMatr );

    677 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateZ(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, and qreal.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateZ(), expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, and qreal.

    -

    ◆ TEST_CASE() [44/123]

    +

    ◆ TEST_CASE() [45/124]

    @@ -7207,12 +7375,12 @@

    753  CLEANUP_TEST( quregVec, quregMatr );

    754 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledTwoQubitUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, and toComplexMatrix4().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledTwoQubitUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, and toComplexMatrix4().

    -

    ◆ TEST_CASE() [45/123]

    +

    ◆ TEST_CASE() [46/124]

    @@ -7286,12 +7454,12 @@

    805  CLEANUP_TEST( quregVec, quregMatr );

    806 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, and toComplexMatrix2().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, and toComplexMatrix2().

    -

    ◆ TEST_CASE() [46/123]

    +

    ◆ TEST_CASE() [47/124]

    @@ -7364,7 +7532,7 @@

    -

    ◆ TEST_CASE() [47/123]

    +

    ◆ TEST_CASE() [48/124]

    @@ -7414,12 +7582,12 @@

    122  }

    123 }
    -

    References areEqual(), createComplexMatrixN(), destroyComplexMatrixN(), getZeroMatrix(), and toQMatrix().

    +

    References areEqual(), createComplexMatrixN(), destroyComplexMatrixN(), getZeroMatrix(), and toQMatrix().

    -

    ◆ TEST_CASE() [48/123]

    +

    ◆ TEST_CASE() [49/124]

    @@ -7500,12 +7668,12 @@

    181  }

    182 }
    -

    References areEqual(), calcLog2(), createDensityQureg(), destroyQureg(), getZeroMatrix(), QuESTEnv::numRanks, and QUEST_ENV.

    +

    References areEqual(), calcLog2(), createDensityQureg(), destroyQureg(), getZeroMatrix(), QuESTEnv::numRanks, and QUEST_ENV.

    -

    ◆ TEST_CASE() [49/123]

    +

    ◆ TEST_CASE() [50/124]

    @@ -7592,12 +7760,12 @@

    246  }

    247 }
    -

    References areEqual(), calcLog2(), DiagonalOp::chunkId, createDiagonalOp(), destroyDiagonalOp(), DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, QUEST_ENV, QuESTEnv::rank, DiagonalOp::real, and toQVector().

    +

    References areEqual(), calcLog2(), DiagonalOp::chunkId, createDiagonalOp(), destroyDiagonalOp(), DiagonalOp::imag, DiagonalOp::numChunks, DiagonalOp::numElemsPerChunk, DiagonalOp::numQubits, QuESTEnv::numRanks, QUEST_ENV, QuESTEnv::rank, DiagonalOp::real, and toQVector().

    -

    ◆ TEST_CASE() [50/123]

    +

    ◆ TEST_CASE() [51/124]

    @@ -7784,12 +7952,12 @@

    411  deleteFilesWithPrefixSynch(fnPrefix);

    412 }
    -

    References areEqual(), calcLog2(), createDiagonalOpFromPauliHamilFile(), createPauliHamil(), deleteFilesWithPrefixSynch(), destroyDiagonalOp(), destroyPauliHamil(), QuESTEnv::numRanks, PAULI_I, PAULI_Z, PauliHamil::pauliCodes, qreal, QUEST_ENV, QuESTEnv::rank, setRandomDiagPauliHamil(), setUniqueFilename(), syncQuESTEnv(), PauliHamil::termCoeffs, toQMatrix(), and writeToFileSynch().

    +

    References areEqual(), calcLog2(), createDiagonalOpFromPauliHamilFile(), createPauliHamil(), deleteFilesWithPrefixSynch(), destroyDiagonalOp(), destroyPauliHamil(), QuESTEnv::numRanks, PAULI_I, PAULI_Z, PauliHamil::pauliCodes, qreal, QUEST_ENV, QuESTEnv::rank, setRandomDiagPauliHamil(), setUniqueFilename(), syncQuESTEnv(), PauliHamil::termCoeffs, toQMatrix(), and writeToFileSynch().

    -

    ◆ TEST_CASE() [51/123]

    +

    ◆ TEST_CASE() [52/124]

    @@ -7858,12 +8026,12 @@

    458  }

    459 }
    -

    References createPauliHamil(), destroyPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PauliHamil::pauliCodes, and PauliHamil::termCoeffs.

    +

    References createPauliHamil(), destroyPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PauliHamil::pauliCodes, and PauliHamil::termCoeffs.

    -

    ◆ TEST_CASE() [52/123]

    +

    ◆ TEST_CASE() [53/124]

    @@ -8016,12 +8184,12 @@

    589  deleteFilesWithPrefixSynch(fn);

    590 }
    -

    References createPauliHamilFromFile(), deleteFilesWithPrefixSynch(), destroyPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, qreal, QUEST_ENV, QuESTEnv::rank, setRandomPauliSum(), setUniqueFilename(), syncQuESTEnv(), PauliHamil::termCoeffs, and writeToFileSynch().

    +

    References createPauliHamilFromFile(), deleteFilesWithPrefixSynch(), destroyPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PauliHamil::pauliCodes, qreal, QUEST_ENV, QuESTEnv::rank, setRandomPauliSum(), setUniqueFilename(), syncQuESTEnv(), PauliHamil::termCoeffs, and writeToFileSynch().

    -

    ◆ TEST_CASE() [53/123]

    +

    ◆ TEST_CASE() [54/124]

    @@ -8058,7 +8226,7 @@

    -

    ◆ TEST_CASE() [54/123]

    +

    ◆ TEST_CASE() [55/124]

    @@ -8137,12 +8305,12 @@

    658  }

    659 }
    -

    References areEqual(), calcLog2(), createQureg(), destroyQureg(), QuESTEnv::numRanks, and QUEST_ENV.

    +

    References areEqual(), calcLog2(), createQureg(), destroyQureg(), QuESTEnv::numRanks, and QUEST_ENV.

    -

    ◆ TEST_CASE() [55/123]

    +

    ◆ TEST_CASE() [56/124]

    @@ -8195,12 +8363,12 @@

    689  }

    690 }
    -

    References destroyComplexMatrixN(), and ComplexMatrixN::real.

    +

    References destroyComplexMatrixN(), and ComplexMatrixN::real.

    -

    ◆ TEST_CASE() [56/123]

    +

    ◆ TEST_CASE() [57/124]

    @@ -8237,7 +8405,7 @@

    -

    ◆ TEST_CASE() [57/123]

    +

    ◆ TEST_CASE() [58/124]

    @@ -8279,7 +8447,7 @@

    -

    ◆ TEST_CASE() [58/123]

    +

    ◆ TEST_CASE() [59/124]

    @@ -8316,7 +8484,7 @@

    -

    ◆ TEST_CASE() [59/123]

    +

    ◆ TEST_CASE() [60/124]

    @@ -8358,7 +8526,7 @@

    -

    ◆ TEST_CASE() [60/123]

    +

    ◆ TEST_CASE() [61/124]

    @@ -8400,7 +8568,7 @@

    -

    ◆ TEST_CASE() [61/123]

    +

    ◆ TEST_CASE() [62/124]

    @@ -8461,12 +8629,12 @@

    1302  destroyQureg(vec, QUEST_ENV);

    1303 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    +

    References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    -

    ◆ TEST_CASE() [62/123]

    +

    ◆ TEST_CASE() [63/124]

    @@ -8531,12 +8699,12 @@

    1345  destroyQureg(mat, QUEST_ENV);

    1346 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getDensityAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQMatrix().

    +

    References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getDensityAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQMatrix().

    -

    ◆ TEST_CASE() [63/123]

    +

    ◆ TEST_CASE() [64/124]

    @@ -8596,12 +8764,12 @@

    1383  destroyQureg(vec, QUEST_ENV);

    1384 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getImagAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    +

    References createDensityQureg(), createQureg(), destroyQureg(), getImagAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    -

    ◆ TEST_CASE() [64/123]

    +

    ◆ TEST_CASE() [65/124]

    @@ -8653,12 +8821,12 @@

    1413  }

    1414 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getNumAmps(), NUM_QUBITS, and QUEST_ENV.

    +

    References createDensityQureg(), createQureg(), destroyQureg(), getNumAmps(), NUM_QUBITS, and QUEST_ENV.

    -

    ◆ TEST_CASE() [65/123]

    +

    ◆ TEST_CASE() [66/124]

    @@ -8713,12 +8881,12 @@

    1446  }

    1447 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getNumQubits(), NUM_QUBITS, and QUEST_ENV.

    +

    References createDensityQureg(), createQureg(), destroyQureg(), getNumQubits(), NUM_QUBITS, and QUEST_ENV.

    -

    ◆ TEST_CASE() [66/123]

    +

    ◆ TEST_CASE() [67/124]

    @@ -8779,12 +8947,12 @@

    1485  destroyQureg(vec, QUEST_ENV);

    1486 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getProbAmp(), initDebugState(), NUM_QUBITS, qreal, QUEST_ENV, and toQVector().

    +

    References createDensityQureg(), createQureg(), destroyQureg(), getProbAmp(), initDebugState(), NUM_QUBITS, qreal, QUEST_ENV, and toQVector().

    -

    ◆ TEST_CASE() [67/123]

    +

    ◆ TEST_CASE() [68/124]

    @@ -8844,12 +9012,12 @@

    1523  destroyQureg(vec, QUEST_ENV);

    1524 }
    -

    References createDensityQureg(), createQureg(), destroyQureg(), getRealAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    +

    References createDensityQureg(), createQureg(), destroyQureg(), getRealAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

    -

    ◆ TEST_CASE() [68/123]

    +

    ◆ TEST_CASE() [69/124]

    @@ -8886,7 +9054,7 @@

    -

    ◆ TEST_CASE() [69/123]

    +

    ◆ TEST_CASE() [70/124]

    @@ -8948,12 +9116,12 @@

    845  CLEANUP_TEST( quregVec, quregMatr );

    846 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, hadamard(), NUM_QUBITS, PREPARE_TEST, and qreal.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, hadamard(), NUM_QUBITS, PREPARE_TEST, and qreal.

    -

    ◆ TEST_CASE() [70/123]

    +

    ◆ TEST_CASE() [71/124]

    @@ -9013,7 +9181,7 @@

    -

    ◆ TEST_CASE() [71/123]

    +

    ◆ TEST_CASE() [72/124]

    -

    ◆ TEST_CASE() [75/123]

    +

    ◆ TEST_CASE() [76/124]

    @@ -9394,12 +9562,12 @@

    957  }

    958 }
    -

    References createPauliHamil(), destroyPauliHamil(), initPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qreal, and PauliHamil::termCoeffs.

    +

    References createPauliHamil(), destroyPauliHamil(), initPauliHamil(), PauliHamil::numQubits, PauliHamil::numSumTerms, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PauliHamil::pauliCodes, qreal, and PauliHamil::termCoeffs.

    -

    ◆ TEST_CASE() [76/123]

    +

    ◆ TEST_CASE() [77/124]

    -

    ◆ TEST_CASE() [78/123]

    +

    ◆ TEST_CASE() [79/124]

    @@ -9597,51 +9765,64 @@

    -
    See also
    initStateFromAmps
    +
    See also
    initStateFromAmps
    Author
    Tyson Jones

    Definition at line 286 of file test_state_initialisations.cpp.

    286  {
    287 
    -
    289 
    -
    290  SECTION( "correctness" ) {
    -
    291 
    -
    292  SECTION( "state-vector" ) {
    -
    293 
    -
    294  // create arbitrary (but distinctly non-zero) amplitudes
    -
    295  qreal ampsRe[vec.numAmpsTotal];
    -
    296  qreal ampsIm[vec.numAmpsTotal];
    -
    297  QVector vecRef = QVector(vec.numAmpsTotal);
    -
    298  for (int i=0; i<vec.numAmpsTotal; i++) {
    -
    299  ampsRe[i] = 2*i;
    -
    300  ampsIm[i] = 2*i + 1;
    -
    301  vecRef[i] = (ampsRe[i]) + ampsIm[i] * (qcomp) 1i;;
    -
    302  }
    -
    303 
    -
    304  initBlankState(vec);
    + +
    290 
    +
    291  SECTION( "correctness" ) {
    +
    292 
    +
    293  SECTION( "state-vector" ) {
    +
    294 
    +
    295  // create random (unnormalised) vector
    +
    296  QVector vecRef = getRandomQVector(1<<NUM_QUBITS);
    +
    297 
    +
    298  qreal ampsRe[vec.numAmpsTotal];
    +
    299  qreal ampsIm[vec.numAmpsTotal];
    +
    300  for (size_t i=0; i<vecRef.size(); i++) {
    +
    301  ampsRe[i] = real(vecRef[i]);
    +
    302  ampsIm[i] = imag(vecRef[i]);
    +
    303  }
    +
    304 
    305  initStateFromAmps(vec, ampsRe, ampsIm);
    306  REQUIRE( areEqual(vec, vecRef) );
    307  }
    -
    308  }
    -
    309  SECTION( "input validation" ) {
    -
    310 
    -
    311  SECTION( "density-matrix" ) {
    +
    308  SECTION( "density-matrix" ) {
    +
    309 
    +
    310  // create random (unnormalised) matrix
    +
    311  QMatrix matRef = getRandomQMatrix(1<<NUM_QUBITS);
    312 
    - -
    314  REQUIRE_THROWS_WITH( initStateFromAmps(mat, NULL, NULL), Contains("valid only for state-vectors") );
    -
    315  destroyQureg(mat, QUEST_ENV);
    -
    316  }
    -
    317  }
    -
    318  destroyQureg(vec, QUEST_ENV);
    -
    319 }
    +
    313  qreal ampsRe[mat.numAmpsTotal];
    +
    314  qreal ampsIm[mat.numAmpsTotal];
    +
    315 
    +
    316  // populate column-wise
    +
    317  long long int i=0;
    +
    318  for (size_t c=0; c<matRef.size(); c++) {
    +
    319  for (size_t r=0; r<matRef.size(); r++) {
    +
    320  ampsRe[i] = real(matRef[r][c]);
    +
    321  ampsIm[i] = imag(matRef[r][c]);
    +
    322  i++;
    +
    323  }
    +
    324  }
    +
    325 
    +
    326  initStateFromAmps(mat, ampsRe, ampsIm);
    +
    327  REQUIRE( areEqual(mat, matRef) );
    +
    328  }
    +
    329  }
    +
    330  destroyQureg(vec, QUEST_ENV);
    +
    331  destroyQureg(mat, QUEST_ENV);
    +
    332 }
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initStateFromAmps(), NUM_QUBITS, Qureg::numAmpsTotal, qcomp, qreal, and QUEST_ENV.

    +

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomQMatrix(), getRandomQVector(), initStateFromAmps(), NUM_QUBITS, Qureg::numAmpsTotal, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [79/123]

    +

    ◆ TEST_CASE() [80/124]

    @@ -9668,48 +9849,48 @@

    See also
    initZeroState
    Author
    Tyson Jones
    -

    Definition at line 327 of file test_state_initialisations.cpp.

    -
    327  {
    -
    328 
    - - -
    331 
    -
    332  SECTION( "correctness" ) {
    -
    333 
    -
    334  SECTION( "state-vector" ) {
    -
    335 
    -
    336  initBlankState(vec);
    -
    337  initZeroState(vec);
    -
    338 
    -
    339  QVector refVec = QVector(vec.numAmpsTotal);
    -
    340  refVec[0] = 1;
    -
    341  REQUIRE( areEqual(vec, refVec) );
    -
    342  }
    -
    343  SECTION( "density-matrix" ) {
    -
    344 
    -
    345  initBlankState(mat);
    -
    346  initZeroState(mat);
    -
    347 
    -
    348  QMatrix refMat = getZeroMatrix(1<<mat.numQubitsRepresented);
    -
    349  refMat[0][0] = 1;
    -
    350  REQUIRE( areEqual(mat, refMat) );
    -
    351  }
    -
    352  }
    -
    353  SECTION( "input validation" ) {
    -
    354 
    -
    355  // no input validation
    -
    356  SUCCEED( );
    -
    357  }
    -
    358  destroyQureg(vec, QUEST_ENV);
    -
    359  destroyQureg(mat, QUEST_ENV);
    -
    360 }
    +

    Definition at line 340 of file test_state_initialisations.cpp.

    +
    340  {
    +
    341 
    + + +
    344 
    +
    345  SECTION( "correctness" ) {
    +
    346 
    +
    347  SECTION( "state-vector" ) {
    +
    348 
    +
    349  initBlankState(vec);
    +
    350  initZeroState(vec);
    +
    351 
    +
    352  QVector refVec = QVector(vec.numAmpsTotal);
    +
    353  refVec[0] = 1;
    +
    354  REQUIRE( areEqual(vec, refVec) );
    +
    355  }
    +
    356  SECTION( "density-matrix" ) {
    +
    357 
    +
    358  initBlankState(mat);
    +
    359  initZeroState(mat);
    +
    360 
    +
    361  QMatrix refMat = getZeroMatrix(1<<mat.numQubitsRepresented);
    +
    362  refMat[0][0] = 1;
    +
    363  REQUIRE( areEqual(mat, refMat) );
    +
    364  }
    +
    365  }
    +
    366  SECTION( "input validation" ) {
    +
    367 
    +
    368  // no input validation
    +
    369  SUCCEED( );
    +
    370  }
    +
    371  destroyQureg(vec, QUEST_ENV);
    +
    372  destroyQureg(mat, QUEST_ENV);
    +
    373 }

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), initZeroState(), NUM_QUBITS, Qureg::numAmpsTotal, Qureg::numQubitsRepresented, and QUEST_ENV.

    -

    ◆ TEST_CASE() [80/123]

    +

    ◆ TEST_CASE() [81/124]

    @@ -9823,12 +10004,12 @@

    204  destroyQureg(mat, QUEST_ENV);

    205 }
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measure(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    +

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measure(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [81/123]

    +

    ◆ TEST_CASE() [82/124]

    @@ -9945,12 +10126,12 @@

    299  destroyQureg(mat, QUEST_ENV);

    300 }
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measureWithStats(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    +

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measureWithStats(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

    -

    ◆ TEST_CASE() [82/123]

    +

    ◆ TEST_CASE() [83/124]

    @@ -10022,12 +10203,12 @@

    64  destroyQureg(qureg, QUEST_ENV);

    65 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDamping(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDamping(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [83/123]

    +

    ◆ TEST_CASE() [84/124]

    @@ -10110,12 +10291,12 @@

    125  destroyQureg(qureg2, QUEST_ENV);

    126 }
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), mixDensityMatrix(), NUM_QUBITS, Qureg::numQubitsRepresented, qreal, QUEST_ENV, and toQMatrix().

    +

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), mixDensityMatrix(), NUM_QUBITS, Qureg::numQubitsRepresented, qreal, QUEST_ENV, and toQMatrix().

    -

    ◆ TEST_CASE() [84/123]

    +

    ◆ TEST_CASE() [85/124]

    @@ -10183,12 +10364,12 @@

    171  destroyQureg(qureg, QUEST_ENV);

    172 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [85/123]

    +

    ◆ TEST_CASE() [86/124]

    @@ -10259,12 +10440,12 @@

    220  destroyQureg(qureg, QUEST_ENV);

    221 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDepolarising(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and QUEST_ENV.

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDepolarising(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [86/123]

    +

    ◆ TEST_CASE() [87/124]

    @@ -10360,12 +10541,12 @@

    585  destroyQureg(qureg, QUEST_ENV);

    586 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix2::real, and toComplexMatrix2().

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix2::real, and toComplexMatrix2().

    -

    ◆ TEST_CASE() [87/123]

    +

    ◆ TEST_CASE() [88/124]

    @@ -10600,12 +10781,12 @@

    433  destroyQureg(qureg, QUEST_ENV);

    434 }
    -

    References applyReferenceOp(), areEqual(), calcLog2(), createComplexMatrixN(), createQureg(), destroyComplexMatrixN(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixMultiQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    +

    References applyReferenceOp(), areEqual(), calcLog2(), createComplexMatrixN(), createQureg(), destroyComplexMatrixN(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixMultiQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    -

    ◆ TEST_CASE() [88/123]

    +

    ◆ TEST_CASE() [89/124]

    @@ -10705,12 +10886,12 @@

    511  destroyQureg(qureg, QUEST_ENV);

    512 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixPauli(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and QUEST_ENV.

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixPauli(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [89/123]

    +

    ◆ TEST_CASE() [90/124]

    @@ -10791,12 +10972,12 @@

    644  destroyQureg(qureg, QUEST_ENV);

    645 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixTwoQubitDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixTwoQubitDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [90/123]

    +

    ◆ TEST_CASE() [91/124]

    @@ -10885,12 +11066,12 @@

    711  destroyQureg(qureg, QUEST_ENV);

    712 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getKroneckerProduct(), getRandomReal(), mixTwoQubitDepolarising(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and QUEST_ENV.

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getKroneckerProduct(), getRandomReal(), mixTwoQubitDepolarising(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and QUEST_ENV.

    -

    ◆ TEST_CASE() [91/123]

    +

    ◆ TEST_CASE() [92/124]

    @@ -10993,12 +11174,12 @@

    792  destroyQureg(qureg, QUEST_ENV);

    793 }
    -

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixTwoQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix4::real, and toComplexMatrix4().

    +

    References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixTwoQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix4::real, and toComplexMatrix4().

    -

    ◆ TEST_CASE() [92/123]

    +

    ◆ TEST_CASE() [93/124]

    @@ -11116,12 +11297,12 @@

    941  CLEANUP_TEST( quregVec, quregMatr );

    942 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiControlledMultiQubitNot(), NUM_QUBITS, PREPARE_TEST, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiControlledMultiQubitNot(), NUM_QUBITS, PREPARE_TEST, and sublists().

    -

    ◆ TEST_CASE() [93/123]

    +

    ◆ TEST_CASE() [94/124]

    @@ -11315,12 +11496,12 @@

    1113  CLEANUP_TEST( quregVec, quregMatr );

    1114 }
    -

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiControlledMultiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    +

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiControlledMultiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    -

    ◆ TEST_CASE() [94/123]

    +

    ◆ TEST_CASE() [95/124]

    @@ -11505,12 +11686,12 @@

    1276  CLEANUP_TEST( quregVec, quregMatr );

    1277 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfPauliMatrix(), getKroneckerProduct(), getRandomInt(), getRandomReal(), M_PI, multiControlledMultiRotatePauli(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PREPARE_TEST, qcomp, qreal, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfPauliMatrix(), getKroneckerProduct(), getRandomInt(), getRandomReal(), M_PI, multiControlledMultiRotatePauli(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PREPARE_TEST, qcomp, qreal, and sublists().

    -

    ◆ TEST_CASE() [95/123]

    +

    ◆ TEST_CASE() [96/124]

    @@ -11649,12 +11830,12 @@

    1393  CLEANUP_TEST( quregVec, quregMatr );

    1394 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfDiagonalMatrix(), getKroneckerProduct(), getRandomReal(), M_PI, multiControlledMultiRotateZ(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfDiagonalMatrix(), getKroneckerProduct(), getRandomReal(), M_PI, multiControlledMultiRotateZ(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and sublists().

    -

    ◆ TEST_CASE() [96/123]

    +

    ◆ TEST_CASE() [97/124]

    @@ -11732,12 +11913,12 @@

    1449  CLEANUP_TEST( quregVec, quregMatr );

    1450 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiControlledPhaseFlip(), NUM_QUBITS, PREPARE_TEST, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiControlledPhaseFlip(), NUM_QUBITS, PREPARE_TEST, and sublists().

    -

    ◆ TEST_CASE() [97/123]

    +

    ◆ TEST_CASE() [98/124]

    @@ -11814,12 +11995,12 @@

    1504  CLEANUP_TEST( quregVec, quregMatr );

    1505 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), M_PI, multiControlledPhaseShift(), NUM_QUBITS, PREPARE_TEST, qreal, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), M_PI, multiControlledPhaseShift(), NUM_QUBITS, PREPARE_TEST, qreal, and sublists().

    -

    ◆ TEST_CASE() [98/123]

    +

    ◆ TEST_CASE() [99/124]

    @@ -11945,12 +12126,12 @@

    1608  CLEANUP_TEST( quregVec, quregMatr );

    1609 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledTwoQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, sublists(), and toComplexMatrix4().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledTwoQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, sublists(), and toComplexMatrix4().

    -

    ◆ TEST_CASE() [99/123]

    +

    ◆ TEST_CASE() [100/124]

    @@ -12043,12 +12224,12 @@

    1679  CLEANUP_TEST( quregVec, quregMatr );

    1680 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

    -

    ◆ TEST_CASE() [100/123]

    +

    ◆ TEST_CASE() [101/124]

    @@ -12137,12 +12318,12 @@

    1746  CLEANUP_TEST( quregVec, quregMatr );

    1747 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiQubitNot(), NUM_QUBITS, PREPARE_TEST, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiQubitNot(), NUM_QUBITS, PREPARE_TEST, and sublists().

    -

    ◆ TEST_CASE() [101/123]

    +

    ◆ TEST_CASE() [102/124]

    @@ -12283,12 +12464,12 @@

    1865  CLEANUP_TEST( quregVec, quregMatr );

    1866 }
    -

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    +

    References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

    -

    ◆ TEST_CASE() [102/123]

    +

    ◆ TEST_CASE() [103/124]

    @@ -12413,12 +12594,12 @@

    1968  CLEANUP_TEST( quregVec, quregMatr );

    1969 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfPauliMatrix(), getKroneckerProduct(), getRandomInt(), getRandomReal(), M_PI, multiRotatePauli(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PREPARE_TEST, qcomp, qreal, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfPauliMatrix(), getKroneckerProduct(), getRandomInt(), getRandomReal(), M_PI, multiRotatePauli(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PREPARE_TEST, qcomp, qreal, and sublists().

    -

    ◆ TEST_CASE() [103/123]

    +

    ◆ TEST_CASE() [104/124]

    @@ -12513,12 +12694,12 @@

    2041  CLEANUP_TEST( quregVec, quregMatr );

    2042 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfDiagonalMatrix(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomReal(), M_PI, multiRotateZ(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and sublists().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfDiagonalMatrix(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomReal(), M_PI, multiRotateZ(), NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and sublists().

    -

    ◆ TEST_CASE() [104/123]

    +

    ◆ TEST_CASE() [105/124]

    @@ -12649,12 +12830,12 @@

    2150  CLEANUP_TEST( quregVec, quregMatr );

    2151 }
    -

    References applyReferenceOp(), areEqual(), bitsets(), CLEANUP_TEST, getRandomUnitary(), multiStateControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

    +

    References applyReferenceOp(), areEqual(), bitsets(), CLEANUP_TEST, getRandomUnitary(), multiStateControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

    -

    ◆ TEST_CASE() [105/123]

    +

    ◆ TEST_CASE() [106/124]

    @@ -12715,12 +12896,12 @@

    2189  CLEANUP_TEST( quregVec, quregMatr );

    2190 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliX(), and PREPARE_TEST.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliX(), and PREPARE_TEST.

    -

    ◆ TEST_CASE() [106/123]

    +

    ◆ TEST_CASE() [107/124]

    @@ -12781,12 +12962,12 @@

    2228  CLEANUP_TEST( quregVec, quregMatr );

    2229 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliY(), PREPARE_TEST, and qcomp.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliY(), PREPARE_TEST, and qcomp.

    -

    ◆ TEST_CASE() [107/123]

    +

    ◆ TEST_CASE() [108/124]

    @@ -12847,12 +13028,12 @@

    2267  CLEANUP_TEST( quregVec, quregMatr );

    2268 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliZ(), and PREPARE_TEST.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliZ(), and PREPARE_TEST.

    -

    ◆ TEST_CASE() [108/123]

    +

    ◆ TEST_CASE() [109/124]

    @@ -12914,12 +13095,12 @@

    2307  CLEANUP_TEST( quregVec, quregMatr );

    2308 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), M_PI, NUM_QUBITS, phaseShift(), PREPARE_TEST, and qreal.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), M_PI, NUM_QUBITS, phaseShift(), PREPARE_TEST, and qreal.

    -

    ◆ TEST_CASE() [109/123]

    +

    ◆ TEST_CASE() [110/124]

    @@ -12997,12 +13178,12 @@

    2363  CLEANUP_TEST( quregVec, quregMatr );

    2364 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, qreal, rotateAroundAxis(), Vector::x, Vector::y, and Vector::z.

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, qreal, rotateAroundAxis(), Vector::x, Vector::y, and Vector::z.

    -

    ◆ TEST_CASE() [110/123]

    +

    ◆ TEST_CASE() [111/124]

    @@ -13066,12 +13247,12 @@

    2405  CLEANUP_TEST( quregVec, quregMatr );

    2406 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and rotateX().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qcomp, qreal, and rotateX().

    -

    ◆ TEST_CASE() [111/123]

    +

    ◆ TEST_CASE() [112/124]

    @@ -13133,12 +13314,12 @@

    2445  CLEANUP_TEST( quregVec, quregMatr );

    2446 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qreal, and rotateY().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qreal, and rotateY().

    -

    ◆ TEST_CASE() [112/123]

    +

    ◆ TEST_CASE() [113/124]

    @@ -13200,12 +13381,12 @@

    2485  CLEANUP_TEST( quregVec, quregMatr );

    2486 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qreal, and rotateZ().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), M_PI, NUM_QUBITS, PREPARE_TEST, qreal, and rotateZ().

    -

    ◆ TEST_CASE() [113/123]

    +

    ◆ TEST_CASE() [114/124]

    @@ -13232,77 +13413,77 @@

    See also
    setAmps
    Author
    Tyson Jones
    -

    Definition at line 368 of file test_state_initialisations.cpp.

    -
    368  {
    -
    369 
    - -
    371 
    -
    372  int maxInd = vec.numAmpsTotal;
    -
    373  qreal reals[maxInd];
    -
    374  qreal imags[maxInd];
    -
    375 
    -
    376  SECTION( "correctness" ) {
    -
    377 
    -
    378  SECTION( "state-vector" ) {
    -
    379 
    -
    380  // all valid number of amplitudes and offsets
    -
    381  int startInd = GENERATE_COPY( range(0,maxInd) );
    -
    382  int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
    -
    383 
    -
    384  // generate random amplitudes
    -
    385  for (int i=0; i<numAmps; i++) {
    -
    386  reals[i] = getRandomReal(-5,5);
    -
    387  imags[i] = getRandomReal(-5,5);
    -
    388  }
    -
    389 
    -
    390  // check both specified and un-specified amplitudes are correctly handled
    -
    391  initDebugState(vec);
    -
    392  QVector vecRef = toQVector(vec);
    -
    393 
    -
    394  setAmps(vec, startInd, reals, imags, numAmps);
    -
    395  for (int i=0; i<numAmps; i++)
    -
    396  vecRef[startInd+i] = reals[i] + imags[i] * (qcomp) 1i;
    -
    397 
    -
    398  REQUIRE( areEqual(vec, vecRef) );
    -
    399  }
    -
    400  }
    -
    401  SECTION( "input validation" ) {
    -
    402 
    -
    403  SECTION( "start index" ) {
    -
    404 
    -
    405  int startInd = GENERATE_COPY( -1, maxInd );
    -
    406  int numAmps = 0;
    -
    407  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
    -
    408  }
    -
    409 
    -
    410  SECTION( "number of amplitudes" ) {
    -
    411 
    -
    412  // independent
    -
    413  int startInd = 0;
    -
    414  int numAmps = GENERATE_COPY( -1, maxInd+1 );
    -
    415  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
    -
    416 
    -
    417  // invalid considering start-index
    -
    418  startInd = maxInd - 1;
    -
    419  numAmps = 2;
    -
    420  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("More amplitudes given than exist") );
    +

    Definition at line 381 of file test_state_initialisations.cpp.

    +
    381  {
    +
    382 
    + +
    384 
    +
    385  int maxInd = vec.numAmpsTotal;
    +
    386  qreal reals[maxInd];
    +
    387  qreal imags[maxInd];
    +
    388 
    +
    389  SECTION( "correctness" ) {
    +
    390 
    +
    391  SECTION( "state-vector" ) {
    +
    392 
    +
    393  // all valid number of amplitudes and offsets
    +
    394  int startInd = GENERATE_COPY( range(0,maxInd) );
    +
    395  int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
    +
    396 
    +
    397  // generate random amplitudes
    +
    398  for (int i=0; i<numAmps; i++) {
    +
    399  reals[i] = getRandomReal(-5,5);
    +
    400  imags[i] = getRandomReal(-5,5);
    +
    401  }
    +
    402 
    +
    403  // check both specified and un-specified amplitudes are correctly handled
    +
    404  initDebugState(vec);
    +
    405  QVector vecRef = toQVector(vec);
    +
    406 
    +
    407  setAmps(vec, startInd, reals, imags, numAmps);
    +
    408  for (int i=0; i<numAmps; i++)
    +
    409  vecRef[startInd+i] = reals[i] + imags[i] * (qcomp) 1i;
    +
    410 
    +
    411  REQUIRE( areEqual(vec, vecRef) );
    +
    412  }
    +
    413  }
    +
    414  SECTION( "input validation" ) {
    +
    415 
    +
    416  SECTION( "start index" ) {
    +
    417 
    +
    418  int startInd = GENERATE_COPY( -1, maxInd );
    +
    419  int numAmps = 0;
    +
    420  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
    421  }
    -
    422  SECTION( "density-matrix" ) {
    -
    423 
    - -
    425  REQUIRE_THROWS_WITH( setAmps(mat, 0, reals, imags, 0), Contains("valid only for state-vectors") );
    -
    426  destroyQureg(mat, QUEST_ENV);
    -
    427  }
    -
    428  }
    -
    429  destroyQureg(vec, QUEST_ENV);
    -
    430 }
    +
    422 
    +
    423  SECTION( "number of amplitudes" ) {
    +
    424 
    +
    425  // independent
    +
    426  int startInd = 0;
    +
    427  int numAmps = GENERATE_COPY( -1, maxInd+1 );
    +
    428  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
    +
    429 
    +
    430  // invalid considering start-index
    +
    431  startInd = maxInd - 1;
    +
    432  numAmps = 2;
    +
    433  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("More amplitudes given than exist") );
    +
    434  }
    +
    435  SECTION( "density-matrix" ) {
    +
    436 
    + +
    438  REQUIRE_THROWS_WITH( setAmps(mat, 0, reals, imags, 0), Contains("valid only for state-vectors") );
    +
    439  destroyQureg(mat, QUEST_ENV);
    +
    440  }
    +
    441  }
    +
    442  destroyQureg(vec, QUEST_ENV);
    +
    443 }
    -

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), initDebugState(), NUM_QUBITS, Qureg::numAmpsTotal, qcomp, qreal, QUEST_ENV, setAmps(), and toQVector().

    +

    References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), initDebugState(), NUM_QUBITS, Qureg::numAmpsTotal, qcomp, qreal, QUEST_ENV, setAmps(), and toQVector().

    -

    ◆ TEST_CASE() [114/123]

    +

    ◆ TEST_CASE() [115/124]

    @@ -13392,12 +13573,12 @@

    1025  destroyDiagonalOp(op, QUEST_ENV);

    1026 }
    -

    References areEqual(), calcLog2(), createDiagonalOp(), destroyDiagonalOp(), QuESTEnv::numRanks, qreal, QUEST_ENV, setDiagonalOpElems(), and toQVector().

    +

    References areEqual(), calcLog2(), createDiagonalOp(), destroyDiagonalOp(), QuESTEnv::numRanks, qreal, QUEST_ENV, setDiagonalOpElems(), and toQVector().

    -

    ◆ TEST_CASE() [115/123]

    +

    ◆ TEST_CASE() [116/124]

    @@ -13424,198 +13605,198 @@

    See also
    setWeightedQureg
    Author
    Tyson Jones
    -

    Definition at line 438 of file test_state_initialisations.cpp.

    -
    438  {
    -
    439 
    -
    440  SECTION( "correctness" ) {
    -
    441 
    -
    442  // repeat each test below 10 times
    -
    443  GENERATE( range(0,10) );
    -
    444 
    -
    445  /* note tolerance in areEqual increases with tests, since
    -
    446  * small differences propogate in vecC which is not re-initialised
    -
    447  */
    -
    448 
    -
    449  SECTION( "state-vector" ) {
    -
    450 
    -
    451  // make three random vectors
    - - - -
    455  for (int j=0; j<vecA.numAmpsPerChunk; j++) {
    -
    456  vecA.stateVec.real[j] = getRandomReal(-5,5); vecA.stateVec.imag[j] = getRandomReal(-5,5);
    -
    457  vecB.stateVec.real[j] = getRandomReal(-5,5); vecB.stateVec.imag[j] = getRandomReal(-5,5);
    -
    458  vecC.stateVec.real[j] = getRandomReal(-5,5); vecC.stateVec.imag[j] = getRandomReal(-5,5);
    -
    459  }
    -
    460  copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
    -
    461  QVector refA = toQVector(vecA);
    -
    462  QVector refB = toQVector(vecB);
    -
    463  QVector refC = toQVector(vecC);
    -
    464  QVector refOut;
    -
    465 
    -
    466  // get three random factors
    -
    467  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    468  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    469  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    470  Complex facA = toComplex(numA);
    -
    471  Complex facB = toComplex(numB);
    -
    472  Complex facC = toComplex(numC);
    -
    473 
    -
    474  // check out-qureg is correct, when all quregs are unique...
    -
    475  setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
    -
    476  refOut = numA*refA + numB*refB + numC*refC;
    -
    477  REQUIRE( areEqual(vecC, refOut) );
    +

    Definition at line 451 of file test_state_initialisations.cpp.

    +
    451  {
    +
    452 
    +
    453  SECTION( "correctness" ) {
    +
    454 
    +
    455  // repeat each test below 10 times
    +
    456  GENERATE( range(0,10) );
    +
    457 
    +
    458  /* note tolerance in areEqual increases with tests, since
    +
    459  * small differences propogate in vecC which is not re-initialised
    +
    460  */
    +
    461 
    +
    462  SECTION( "state-vector" ) {
    +
    463 
    +
    464  // make three random vectors
    + + + +
    468  for (int j=0; j<vecA.numAmpsPerChunk; j++) {
    +
    469  vecA.stateVec.real[j] = getRandomReal(-5,5); vecA.stateVec.imag[j] = getRandomReal(-5,5);
    +
    470  vecB.stateVec.real[j] = getRandomReal(-5,5); vecB.stateVec.imag[j] = getRandomReal(-5,5);
    +
    471  vecC.stateVec.real[j] = getRandomReal(-5,5); vecC.stateVec.imag[j] = getRandomReal(-5,5);
    +
    472  }
    +
    473  copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
    +
    474  QVector refA = toQVector(vecA);
    +
    475  QVector refB = toQVector(vecB);
    +
    476  QVector refC = toQVector(vecC);
    +
    477  QVector refOut;
    478 
    -
    479  // ... and that other qureg's aren't modified
    -
    480  REQUIRE( areEqual(vecA, refA) );
    -
    481  REQUIRE( areEqual(vecB, refB) );
    -
    482 
    -
    483  // check quregOut correct, when it's also qureg2
    -
    484  refC = toQVector(vecC);
    -
    485  setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
    -
    486  refOut = numB*refB + numC*refC + numA*refC;
    -
    487  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    -
    488 
    -
    489  // ... and that the remaining qureg is not modified
    -
    490  REQUIRE( areEqual(vecB, refB) );
    +
    479  // get three random factors
    +
    480  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    481  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    482  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    483  Complex facA = toComplex(numA);
    +
    484  Complex facB = toComplex(numB);
    +
    485  Complex facC = toComplex(numC);
    +
    486 
    +
    487  // check out-qureg is correct, when all quregs are unique...
    +
    488  setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
    +
    489  refOut = numA*refA + numB*refB + numC*refC;
    +
    490  REQUIRE( areEqual(vecC, refOut) );
    491 
    -
    492  // check quregOut correct, when it's also qureg1
    -
    493  refC = toQVector(vecC);
    -
    494  setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
    -
    495  refOut = numC*refC + numB*refB + numA*refC;
    -
    496  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    -
    497 
    -
    498  // ... and that the remaining qureg is not modified
    -
    499  REQUIRE( areEqual(vecB, refB) );
    -
    500 
    -
    501  // check quregOut is correct when it's both input quregs
    -
    502  refC = toQVector(vecC);
    -
    503  setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
    -
    504  refOut = numA*refC + numB*refC + numC*refC;
    -
    505  REQUIRE( areEqual(vecC, refOut, 1E3*REAL_EPS) );
    -
    506 
    -
    507  // cleanup
    -
    508  destroyQureg(vecA, QUEST_ENV);
    -
    509  destroyQureg(vecB, QUEST_ENV);
    -
    510  destroyQureg(vecC, QUEST_ENV);
    -
    511  }
    -
    512  SECTION( "density-matrix" ) {
    +
    492  // ... and that other qureg's aren't modified
    +
    493  REQUIRE( areEqual(vecA, refA) );
    +
    494  REQUIRE( areEqual(vecB, refB) );
    +
    495 
    +
    496  // check quregOut correct, when it's also qureg2
    +
    497  refC = toQVector(vecC);
    +
    498  setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
    +
    499  refOut = numB*refB + numC*refC + numA*refC;
    +
    500  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    +
    501 
    +
    502  // ... and that the remaining qureg is not modified
    +
    503  REQUIRE( areEqual(vecB, refB) );
    +
    504 
    +
    505  // check quregOut correct, when it's also qureg1
    +
    506  refC = toQVector(vecC);
    +
    507  setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
    +
    508  refOut = numC*refC + numB*refB + numA*refC;
    +
    509  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    +
    510 
    +
    511  // ... and that the remaining qureg is not modified
    +
    512  REQUIRE( areEqual(vecB, refB) );
    513 
    -
    514  // make three random matrices
    - - - -
    518  for (int j=0; j<matA.numAmpsPerChunk; j++) {
    -
    519  matA.stateVec.real[j] = getRandomReal(-5,5); matA.stateVec.imag[j] = getRandomReal(-5,5);
    -
    520  matB.stateVec.real[j] = getRandomReal(-5,5); matB.stateVec.imag[j] = getRandomReal(-5,5);
    -
    521  matC.stateVec.real[j] = getRandomReal(-5,5); matC.stateVec.imag[j] = getRandomReal(-5,5);
    -
    522  }
    -
    523  copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
    -
    524  QMatrix refA = toQMatrix(matA);
    -
    525  QMatrix refB = toQMatrix(matB);
    -
    526  QMatrix refC = toQMatrix(matC);
    -
    527  QMatrix refOut;
    -
    528 
    -
    529  // get three random factors
    -
    530  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    531  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    532  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    533  Complex facA = toComplex(numA);
    -
    534  Complex facB = toComplex(numB);
    -
    535  Complex facC = toComplex(numC);
    -
    536 
    -
    537  // check out-qureg is correct, when all quregs are unique...
    -
    538  setWeightedQureg(facA, matA, facB, matB, facC, matC);
    -
    539  refOut = numA*refA + numB*refB + numC*refC;
    -
    540  REQUIRE( areEqual(matC, refOut) );
    +
    514  // check quregOut is correct when it's both input quregs
    +
    515  refC = toQVector(vecC);
    +
    516  setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
    +
    517  refOut = numA*refC + numB*refC + numC*refC;
    +
    518  REQUIRE( areEqual(vecC, refOut, 1E3*REAL_EPS) );
    +
    519 
    +
    520  // cleanup
    +
    521  destroyQureg(vecA, QUEST_ENV);
    +
    522  destroyQureg(vecB, QUEST_ENV);
    +
    523  destroyQureg(vecC, QUEST_ENV);
    +
    524  }
    +
    525  SECTION( "density-matrix" ) {
    +
    526 
    +
    527  // make three random matrices
    + + + +
    531  for (int j=0; j<matA.numAmpsPerChunk; j++) {
    +
    532  matA.stateVec.real[j] = getRandomReal(-5,5); matA.stateVec.imag[j] = getRandomReal(-5,5);
    +
    533  matB.stateVec.real[j] = getRandomReal(-5,5); matB.stateVec.imag[j] = getRandomReal(-5,5);
    +
    534  matC.stateVec.real[j] = getRandomReal(-5,5); matC.stateVec.imag[j] = getRandomReal(-5,5);
    +
    535  }
    +
    536  copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
    +
    537  QMatrix refA = toQMatrix(matA);
    +
    538  QMatrix refB = toQMatrix(matB);
    +
    539  QMatrix refC = toQMatrix(matC);
    +
    540  QMatrix refOut;
    541 
    -
    542  // ... and that other qureg's aren't modified
    -
    543  REQUIRE( areEqual(matA, refA) );
    -
    544  REQUIRE( areEqual(matB, refB) );
    -
    545 
    -
    546  // check quregOut correct, when it's also qureg2
    -
    547  refC = toQMatrix(matC);
    -
    548  setWeightedQureg(facB, matB, facC, matC, facA, matC);
    -
    549  refOut = numB*refB + numC*refC + numA*refC;
    -
    550  REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
    -
    551 
    -
    552  // ... and that the remaining qureg is not modified
    -
    553  REQUIRE( areEqual(matB, refB) );
    +
    542  // get three random factors
    +
    543  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    544  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    545  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    546  Complex facA = toComplex(numA);
    +
    547  Complex facB = toComplex(numB);
    +
    548  Complex facC = toComplex(numC);
    +
    549 
    +
    550  // check out-qureg is correct, when all quregs are unique...
    +
    551  setWeightedQureg(facA, matA, facB, matB, facC, matC);
    +
    552  refOut = numA*refA + numB*refB + numC*refC;
    +
    553  REQUIRE( areEqual(matC, refOut) );
    554 
    -
    555  // check quregOut correct, when it's also qureg1
    -
    556  refC = toQMatrix(matC);
    -
    557  setWeightedQureg(facC, matC, facB, matB, facA, matC);
    -
    558  refOut = numC*refC + numB*refB + numA*refC;
    -
    559  REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
    -
    560 
    -
    561  // ... and that the remaining qureg is not modified
    -
    562  REQUIRE( areEqual(matB, refB) );
    -
    563 
    -
    564  // check quregOut is correct when it's both input quregs
    -
    565  refC = toQMatrix(matC);
    -
    566  setWeightedQureg(facA, matC, facB, matC, facC, matC);
    -
    567  refOut = numA*refC + numB*refC + numC*refC;
    -
    568  REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
    -
    569 
    -
    570  // cleanup
    -
    571  destroyQureg(matA, QUEST_ENV);
    -
    572  destroyQureg(matB, QUEST_ENV);
    -
    573  destroyQureg(matC, QUEST_ENV);
    -
    574  }
    -
    575  }
    -
    576  SECTION( "input validation" ) {
    -
    577 
    -
    578  SECTION( "qureg types" ) {
    -
    579 
    - - -
    582  Complex f = {.real=0, .imag=0};
    -
    583 
    -
    584  // two state-vecs, one density-matrix
    -
    585  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    586  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    587  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    588 
    -
    589  // one state-vec, two density-matrices
    -
    590  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    591  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    592  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    593 
    -
    594  destroyQureg(vec, QUEST_ENV);
    -
    595  destroyQureg(mat, QUEST_ENV);
    -
    596  }
    -
    597  SECTION( "qureg dimensions" ) {
    -
    598 
    - -
    600  Qureg vecB = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    - - -
    603  Complex f = {.real=0, .imag=0};
    -
    604 
    -
    605  // state-vecs
    -
    606  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), Contains("Dimensions") );
    -
    607  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), Contains("Dimensions") );
    -
    608  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), Contains("Dimensions") );
    -
    609 
    -
    610  // density-matrices
    -
    611  REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), Contains("Dimensions") );
    -
    612  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), Contains("Dimensions") );
    -
    613  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), Contains("Dimensions") );
    -
    614 
    -
    615  destroyQureg(vecA, QUEST_ENV);
    -
    616  destroyQureg(vecB, QUEST_ENV);
    -
    617  destroyQureg(matA, QUEST_ENV);
    -
    618  destroyQureg(matB, QUEST_ENV);
    -
    619  }
    -
    620  }
    -
    621 }
    +
    555  // ... and that other qureg's aren't modified
    +
    556  REQUIRE( areEqual(matA, refA) );
    +
    557  REQUIRE( areEqual(matB, refB) );
    +
    558 
    +
    559  // check quregOut correct, when it's also qureg2
    +
    560  refC = toQMatrix(matC);
    +
    561  setWeightedQureg(facB, matB, facC, matC, facA, matC);
    +
    562  refOut = numB*refB + numC*refC + numA*refC;
    +
    563  REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
    +
    564 
    +
    565  // ... and that the remaining qureg is not modified
    +
    566  REQUIRE( areEqual(matB, refB) );
    +
    567 
    +
    568  // check quregOut correct, when it's also qureg1
    +
    569  refC = toQMatrix(matC);
    +
    570  setWeightedQureg(facC, matC, facB, matB, facA, matC);
    +
    571  refOut = numC*refC + numB*refB + numA*refC;
    +
    572  REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
    +
    573 
    +
    574  // ... and that the remaining qureg is not modified
    +
    575  REQUIRE( areEqual(matB, refB) );
    +
    576 
    +
    577  // check quregOut is correct when it's both input quregs
    +
    578  refC = toQMatrix(matC);
    +
    579  setWeightedQureg(facA, matC, facB, matC, facC, matC);
    +
    580  refOut = numA*refC + numB*refC + numC*refC;
    +
    581  REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
    +
    582 
    +
    583  // cleanup
    +
    584  destroyQureg(matA, QUEST_ENV);
    +
    585  destroyQureg(matB, QUEST_ENV);
    +
    586  destroyQureg(matC, QUEST_ENV);
    +
    587  }
    +
    588  }
    +
    589  SECTION( "input validation" ) {
    +
    590 
    +
    591  SECTION( "qureg types" ) {
    +
    592 
    + + +
    595  Complex f = {.real=0, .imag=0};
    +
    596 
    +
    597  // two state-vecs, one density-matrix
    +
    598  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    +
    599  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    +
    600  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    +
    601 
    +
    602  // one state-vec, two density-matrices
    +
    603  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    +
    604  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    +
    605  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    +
    606 
    +
    607  destroyQureg(vec, QUEST_ENV);
    +
    608  destroyQureg(mat, QUEST_ENV);
    +
    609  }
    +
    610  SECTION( "qureg dimensions" ) {
    +
    611 
    + +
    613  Qureg vecB = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    + + +
    616  Complex f = {.real=0, .imag=0};
    +
    617 
    +
    618  // state-vecs
    +
    619  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), Contains("Dimensions") );
    +
    620  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), Contains("Dimensions") );
    +
    621  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), Contains("Dimensions") );
    +
    622 
    +
    623  // density-matrices
    +
    624  REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), Contains("Dimensions") );
    +
    625  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), Contains("Dimensions") );
    +
    626  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), Contains("Dimensions") );
    +
    627 
    +
    628  destroyQureg(vecA, QUEST_ENV);
    +
    629  destroyQureg(vecB, QUEST_ENV);
    +
    630  destroyQureg(matA, QUEST_ENV);
    +
    631  destroyQureg(matB, QUEST_ENV);
    +
    632  }
    +
    633  }
    +
    634 }
    -

    References areEqual(), copyStateToGPU(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), NUM_QUBITS, Qureg::numAmpsPerChunk, qcomp, QUEST_ENV, Complex::real, setWeightedQureg(), Qureg::stateVec, toComplex, toQMatrix(), and toQVector().

    +

    References areEqual(), copyStateToGPU(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), NUM_QUBITS, Qureg::numAmpsPerChunk, qcomp, QUEST_ENV, Complex::real, setWeightedQureg(), Qureg::stateVec, toComplex, toQMatrix(), and toQVector().

    -

    ◆ TEST_CASE() [116/123]

    +

    ◆ TEST_CASE() [117/124]

    @@ -13676,12 +13857,12 @@

    2524  CLEANUP_TEST( quregVec, quregMatr );

    2525 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, qcomp, and sGate().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, qcomp, and sGate().

    -

    ◆ TEST_CASE() [117/123]

    +

    ◆ TEST_CASE() [118/124]

    @@ -13753,12 +13934,12 @@

    2574  CLEANUP_TEST( quregVec, quregMatr );

    2575 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, qcomp, and sqrtSwapGate().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, qcomp, and sqrtSwapGate().

    -

    ◆ TEST_CASE() [118/123]

    +

    ◆ TEST_CASE() [119/124]

    @@ -13828,12 +14009,12 @@

    2622  CLEANUP_TEST( quregVec, quregMatr );

    2623 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, and swapGate().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, and swapGate().

    -

    ◆ TEST_CASE() [119/123]

    +

    ◆ TEST_CASE() [120/124]

    @@ -13903,12 +14084,12 @@

    1073  }

    1074 }
    -

    References applyDiagonalOp(), calcLog2(), copyStateFromGPU(), copyStateToGPU(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), DiagonalOp::imag, Qureg::numAmpsPerChunk, DiagonalOp::numElemsPerChunk, QuESTEnv::numRanks, qreal, QUEST_ENV, DiagonalOp::real, Qureg::stateVec, and syncDiagonalOp().

    +

    References applyDiagonalOp(), calcLog2(), copyStateFromGPU(), copyStateToGPU(), createDiagonalOp(), createQureg(), destroyDiagonalOp(), destroyQureg(), DiagonalOp::imag, Qureg::numAmpsPerChunk, DiagonalOp::numElemsPerChunk, QuESTEnv::numRanks, qreal, QUEST_ENV, DiagonalOp::real, Qureg::stateVec, and syncDiagonalOp().

    -

    ◆ TEST_CASE() [120/123]

    +

    ◆ TEST_CASE() [121/124]

    @@ -13969,12 +14150,12 @@

    2661  CLEANUP_TEST( quregVec, quregMatr );

    2662 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), M_PI, NUM_QUBITS, PREPARE_TEST, and tGate().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), M_PI, NUM_QUBITS, PREPARE_TEST, and tGate().

    -

    ◆ TEST_CASE() [121/123]

    +

    ◆ TEST_CASE() [122/124]

    @@ -14016,7 +14197,7 @@

    -

    ◆ TEST_CASE() [122/123]

    +

    ◆ TEST_CASE() [123/124]

    @@ -14103,12 +14284,12 @@

    2726  CLEANUP_TEST( quregVec, quregMatr );

    2727 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, toComplexMatrix4(), and twoQubitUnitary().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, toComplexMatrix4(), and twoQubitUnitary().

    -

    ◆ TEST_CASE() [123/123]

    +

    ◆ TEST_CASE() [124/124]

    @@ -14177,192 +14358,193 @@

    2773  CLEANUP_TEST( quregVec, quregMatr );

    2774 }
    -

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, toComplexMatrix2(), and unitary().

    +

    References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, toComplexMatrix2(), and unitary().

    -
    void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
    Definition: QuEST.c:245
    -
    void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit dephasing noise.
    Definition: QuEST.c:1237
    +
    void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
    Definition: QuEST.c:244
    +
    void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit dephasing noise.
    Definition: QuEST.c:1250
    @ INVERSE_PRODUCT
    Definition: QuEST.h:233
    -
    qreal getProbAmp(Qureg qureg, long long int index)
    Get the probability of a state-vector at an index in the full state vector.
    Definition: QuEST.c:919
    +
    qreal getProbAmp(Qureg qureg, long long int index)
    Get the probability of a state-vector at an index in the full state vector.
    Definition: QuEST.c:932
    void initBlankState(Qureg qureg)
    Initialises a qureg to have all-zero-amplitudes.
    Definition: QuEST.c:119
    Represents a 3-vector of real numbers.
    Definition: QuEST.h:198
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:727
    +
    void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:726
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:304
    -
    void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
    Definition: QuEST.c:1101
    -
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:257
    -
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:221
    -
    void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:814
    -
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:39
    -
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1489
    +
    void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
    Definition: QuEST.c:1114
    +
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:256
    +
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:220
    +
    void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:813
    +
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:45
    +
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1504
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    qreal real[4][4]
    Definition: QuEST.h:177
    -
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    +
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    #define fromComplex(comp)
    void initPureState(Qureg qureg, Qureg pure)
    Initialise qureg into to a given pure state of an equivalent Hilbert dimension.
    Definition: QuEST.c:145
    #define CLEANUP_TEST(quregVec, quregMatr)
    Destroys the data structures made by PREPARE_TEST.
    +
    void applyProjector(Qureg qureg, int qubit, int outcome)
    Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection.
    Definition: QuEST.c:888
    @ PAULI_Z
    Definition: QuEST.h:96
    -
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:602
    +
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:601
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    @ DISTANCE
    Definition: QuEST.h:234
    -
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1259
    -
    int rank
    Definition: QuEST.h:363
    -
    qreal calcTotalProb(Qureg qureg)
    A debugging function which calculates the probability of the qubits in qureg being in any state,...
    Definition: QuEST.c:1130
    -
    void mixDamping(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
    Definition: QuEST.c:1270
    -
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1356
    +
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1272
    +
    int rank
    Definition: QuEST.h:364
    +
    qreal calcTotalProb(Qureg qureg)
    A debugging function which calculates the probability of the qubits in qureg being in any state,...
    Definition: QuEST.c:1143
    +
    void mixDamping(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
    Definition: QuEST.c:1283
    +
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1369
    int numChunks
    The number of nodes between which the elements of this operator are split.
    Definition: QuEST.h:304
    -
    void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:797
    -
    void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
    Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
    Definition: QuEST.c:1163
    +
    void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:796
    +
    void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
    Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
    Definition: QuEST.c:1176
    @ PAULI_I
    Definition: QuEST.h:96
    -
    void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple control and target qubits.
    Definition: QuEST.c:550
    -
    Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
    Get an amplitude from a density matrix at a given row and column.
    Definition: QuEST.c:936
    +
    void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple control and target qubits.
    Definition: QuEST.c:549
    +
    Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
    Get an amplitude from a density matrix at a given row and column.
    Definition: QuEST.c:949
    int getRandomInt(int min, int max)
    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:526
    std::vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
    Returns a random Kraus map of #numOps 2^numQb-by-2^numQb operators, from an undisclosed distribution.
    Definition: utilities.cpp:578
    -
    DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
    Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
    Definition: QuEST.c:1543
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    -
    qreal getImagAmp(Qureg qureg, long long int index)
    Get the imaginary component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:912
    -
    void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
    Definition: QuEST.c:615
    -
    void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
    Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
    Definition: QuEST.c:1301
    +
    DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
    Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
    Definition: QuEST.c:1558
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    +
    qreal getImagAmp(Qureg qureg, long long int index)
    Get the imaginary component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:925
    +
    void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
    Definition: QuEST.c:614
    +
    void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
    Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
    Definition: QuEST.c:1314
    QMatrix getMixedDensityMatrix(std::vector< qreal > probs, std::vector< QVector > states)
    Returns a mixed density matrix formed from mixing the given pure states, which are assumed normalised...
    Definition: utilities.cpp:640
    -
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1516
    -
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1509
    +
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1531
    +
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1524
    qreal z
    Definition: QuEST.h:200
    -
    void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general multi-controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:283
    +
    void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general multi-controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:282
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    -
    qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
    Definition: QuEST.c:953
    +
    qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
    Definition: QuEST.c:966
    #define CLEANUP_TEST(quregVec, quregMatr)
    Destroys the data structures made by PREPARE_TEST.
    @ TWOS_COMPLEMENT
    Definition: QuEST.h:269
    -
    qreal calcPurity(Qureg qureg)
    Calculates the purity of a density matrix, by the trace of the density matrix squared.
    Definition: QuEST.c:1172
    -
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:1153
    -
    int measure(Qureg qureg, int measureQubit)
    Measures a single qubit, collapsing it randomly to 0 or 1.
    Definition: QuEST.c:985
    +
    qreal calcPurity(Qureg qureg)
    Calculates the purity of a density matrix, by the trace of the density matrix squared.
    Definition: QuEST.c:1185
    +
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:1166
    +
    int measure(Qureg qureg, int measureQubit)
    Measures a single qubit, collapsing it randomly to 0 or 1.
    Definition: QuEST.c:998
    QMatrix getRandomUnitary(int numQb)
    Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix.
    Definition: utilities.cpp:530
    -
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
    Definition: QuEST.c:1178
    +
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
    Definition: QuEST.c:1191
    void writeToFileSynch(char *fn, const string &contents)
    Writes contents to the file with filename fn, which is created and/or overwritten.
    Definition: utilities.cpp:1362
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:421
    -
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:349
    +
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:348
    int chunkId
    The position of the chunk of the operator held by this process in the full operator.
    Definition: QuEST.h:306
    @ NORM
    Definition: QuEST.h:232
    void setDiagMatrixOverrides(QMatrix &matr, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Modifies the given diagonal matrix such that the diagonal elements which correspond to the coordinate...
    Definition: utilities.cpp:1316
    QMatrix getKetBra(QVector ket, QVector bra)
    Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i...
    Definition: utilities.cpp:169
    -
    void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1278
    -
    Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    Computes the expected value of the diagonal operator op for state qureg.
    Definition: QuEST.c:1215
    -
    void sGate(Qureg qureg, int targetQubit)
    Apply the single-qubit S gate.
    Definition: QuEST.c:466
    -
    void cloneQureg(Qureg targetQureg, Qureg copyQureg)
    Overwrite the amplitudes of targetQureg with those from copyQureg.
    Definition: QuEST.c:165
    +
    void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1291
    +
    Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    Computes the expected value of the diagonal operator op for state qureg.
    Definition: QuEST.c:1228
    +
    void sGate(Qureg qureg, int targetQubit)
    Apply the single-qubit S gate.
    Definition: QuEST.c:465
    +
    void cloneQureg(Qureg targetQureg, Qureg copyQureg)
    Overwrite the amplitudes of targetQureg with those from copyQureg.
    Definition: QuEST.c:164
    std::vector< QVector > getRandomOrthonormalVectors(int numQb, int numStates)
    Returns a list of random orthonormal complex vectors, from an undisclosed distribution.
    Definition: utilities.cpp:613
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:175
    @ SCALED_INVERSE_DISTANCE
    Definition: QuEST.h:234
    -
    void rotateY(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:199
    -
    void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
    Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
    Definition: QuEST.c:1046
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:361
    -
    void applyQFT(Qureg qureg, int *qubits, int numQubits)
    Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
    Definition: QuEST.c:867
    +
    void rotateY(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:198
    +
    void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
    Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
    Definition: QuEST.c:1059
    +
    Information about the environment the program is running in.
    Definition: QuEST.h:362
    +
    void applyQFT(Qureg qureg, int *qubits, int numQubits)
    Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
    Definition: QuEST.c:866
    @ UNSIGNED
    Definition: QuEST.h:269
    -
    PauliHamil createPauliHamilFromFile(char *fn)
    Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
    Definition: QuEST.c:1405
    -
    void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:744
    -
    void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Introduce a phase factor on state of the passed qubits.
    Definition: QuEST.c:511
    -
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
    Definition: QuEST.c:1528
    +
    PauliHamil createPauliHamilFromFile(char *fn)
    Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
    Definition: QuEST.c:1420
    +
    void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:743
    +
    void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Introduce a phase factor on state of the passed qubits.
    Definition: QuEST.c:510
    +
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
    Definition: QuEST.c:1543
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    @ INVERSE_DISTANCE
    Definition: QuEST.h:234
    #define qreal
    -
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:686
    +
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:685
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    void toQureg(Qureg qureg, QVector vec)
    Initialises the state-vector qureg to have the same amplitudes as vec.
    Definition: utilities.cpp:1201
    -
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
    Definition: QuEST.c:1008
    -
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    -
    void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
    Definition: QuEST.c:588
    -
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:297
    +
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
    Definition: QuEST.c:1021
    +
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    +
    void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
    Definition: QuEST.c:587
    +
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:296
    #define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
    Prepares the needed data structures for unit testing unitaries.
    -
    void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
    Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
    Definition: QuEST.c:669
    +
    void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
    Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
    Definition: QuEST.c:668
    @ PAULI_X
    Definition: QuEST.h:96
    -
    Complex getAmp(Qureg qureg, long long int index)
    Get the complex amplitude at a given index in the state vector.
    Definition: QuEST.c:926
    -
    void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
    Definition: QuEST.c:564
    +
    Complex getAmp(Qureg qureg, long long int index)
    Get the complex amplitude at a given index in the state vector.
    Definition: QuEST.c:939
    +
    void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
    Definition: QuEST.c:563
    QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
    Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrice...
    Definition: utilities.cpp:216
    -
    int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
    Definition: QuEST.c:972
    +
    int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
    Definition: QuEST.c:985
    int numQubitsInStateVec
    Number of qubits in the state-vector - this is double the number represented for mixed states.
    Definition: QuEST.h:329
    -
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:1206
    +
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:1219
    void setUniqueFilename(char *outFn, char *prefix)
    Modifies outFn to be a filename of format prefix_NUM.txt where NUM is a new unique integer so far.
    Definition: utilities.cpp:1358
    -
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:331
    +
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:330
    void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes...
    Definition: utilities.cpp:1229
    void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
    Initialises cm with the values of qm.
    Definition: utilities.cpp:1033
    -
    void rotateX(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:188
    -
    void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
    Definition: QuEST.c:1024
    -
    void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
    Definition: QuEST.c:706
    -
    qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
    Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
    Definition: QuEST.c:1224
    +
    void rotateX(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:187
    +
    void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
    Definition: QuEST.c:1037
    +
    void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
    Definition: QuEST.c:705
    +
    qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
    Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
    Definition: QuEST.c:1237
    qreal y
    Definition: QuEST.h:200
    qcomp expI(qreal phase)
    Returns the unit-norm complex number exp(i*phase).
    Definition: utilities.cpp:417
    std::vector< qcomp > QVector
    A complex vector, which can be zero-initialised with QVector(numAmps).
    Definition: utilities.hpp:60
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:310
    qreal x
    Definition: QuEST.h:200
    -
    void pauliZ(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
    Definition: QuEST.c:455
    +
    void pauliZ(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
    Definition: QuEST.c:454
    phaseFunc
    Flags for specifying named phase functions.
    Definition: QuEST.h:231
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:1113
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:332
    -
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
    Definition: QuEST.c:1114
    +
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
    Definition: QuEST.c:1127
    qreal * termCoeffs
    The real coefficient of each Pauli product. This is an array of length PauliHamil....
    Definition: QuEST.h:283
    -
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:1080
    -
    void swapGate(Qureg qureg, int qb1, int qb2)
    Performs a SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:628
    +
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:1093
    +
    void swapGate(Qureg qureg, int qb1, int qb2)
    Performs a SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:627
    #define qcomp
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    -
    void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
    Initialise state-vector qureg by specifying all amplitudes.
    Definition: QuEST.c:157
    +
    void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
    Initialise qureg by specifying all amplitudes.
    Definition: QuEST.c:157
    ComplexMatrix4 toComplexMatrix4(QMatrix qm)
    Returns a ComplexMatrix4 copy of QMatix qm.
    Definition: utilities.cpp:1027
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    +
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:42
    @ SCALED_PRODUCT
    Definition: QuEST.h:233
    #define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
    #define toComplex(scalar)
    -
    int numRanks
    Definition: QuEST.h:364
    -
    qreal getRealAmp(Qureg qureg, long long int index)
    Get the real component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:905
    -
    void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
    Definition: QuEST.c:576
    +
    int numRanks
    Definition: QuEST.h:365
    +
    qreal getRealAmp(Qureg qureg, long long int index)
    Get the real component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:918
    +
    void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
    Definition: QuEST.c:575
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:300
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:285
    Represents a diagonal complex operator on the full Hilbert state of a Qureg.
    Definition: QuEST.h:297
    @ PAULI_Y
    Definition: QuEST.h:96
    A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
    Definition: QuEST.h:277
    -
    int getNumQubits(Qureg qureg)
    Returns the number of qubits represented by qureg.
    Definition: QuEST.c:895
    -
    Complex calcInnerProduct(Qureg bra, Qureg ket)
    Computes the inner product of two equal-size state vectors, given by.
    Definition: QuEST.c:1137
    +
    int getNumQubits(Qureg qureg)
    Returns the number of qubits represented by qureg.
    Definition: QuEST.c:908
    +
    Complex calcInnerProduct(Qureg bra, Qureg ket)
    Computes the inner product of two equal-size state vectors, given by.
    Definition: QuEST.c:1150
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg, freeing its memory.
    Definition: QuEST.c:77
    -
    void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
    Definition: QuEST.c:849
    +
    void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
    Definition: QuEST.c:848
    @ SCALED_INVERSE_SHIFTED_NORM
    Definition: QuEST.h:232
    -
    void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:314
    +
    void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:313
    QVector getRandomStateVector(int numQb)
    Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.
    Definition: utilities.cpp:468
    void setRandomDiagPauliHamil(PauliHamil hamil)
    Populates hamil with random coefficients and a random amount number of PAULI_I and PAULI_Z operators.
    Definition: utilities.cpp:1241
    -
    void multiQubitNot(Qureg qureg, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
    Definition: QuEST.c:537
    -
    void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
    Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
    Definition: QuEST.c:1311
    +
    void multiQubitNot(Qureg qureg, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
    Definition: QuEST.c:536
    +
    void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
    Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
    Definition: QuEST.c:1324
    qreal ** real
    Definition: QuEST.h:189
    -
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1563
    -
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:1035
    +
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1578
    +
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:1048
    QMatrix getRandomQMatrix(int dim)
    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
    Definition: utilities.cpp:379
    -
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:1090
    -
    void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:762
    -
    void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    Apply a single-qubit unitary parameterised by two given complex scalars.
    Definition: QuEST.c:405
    +
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:1103
    +
    void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:761
    +
    void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    Apply a single-qubit unitary parameterised by two given complex scalars.
    Definition: QuEST.c:404
    void initClassicalState(Qureg qureg, long long int stateInd)
    Initialise qureg into the classical state (also known as a "computational basis state") with index st...
    Definition: QuEST.c:134
    -
    void pauliY(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
    Definition: QuEST.c:444
    +
    void pauliY(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
    Definition: QuEST.c:443
    @ INVERSE_NORM
    Definition: QuEST.h:232
    long long int getTwosComplement(long long int decimal, int numBits)
    Returns the two's complement signed encoding of the unsigned number decimal, which must be a number b...
    Definition: utilities.cpp:1286
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Introduce a phase factor on state of qubits idQubit1 and idQubit2.
    Definition: QuEST.c:499
    -
    void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit dephasing noise.
    Definition: QuEST.c:1247
    -
    void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    Apply a general controlled unitary (single control, single target), which can include a global phase ...
    Definition: QuEST.c:361
    +
    void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Introduce a phase factor on state of qubits idQubit1 and idQubit2.
    Definition: QuEST.c:498
    +
    void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit dephasing noise.
    Definition: QuEST.c:1260
    +
    void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    Apply a general controlled unitary (single control, single target), which can include a global phase ...
    Definition: QuEST.c:360
    qreal ** imag
    Definition: QuEST.h:190
    -
    void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
    Overwrites the entire DiagonalOp op with the given real and imag complex elements.
    Definition: QuEST.c:1522
    -
    void phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Shift the phase between and of a single qubit by a given angle.
    Definition: QuEST.c:488
    +
    void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
    Overwrites the entire DiagonalOp op with the given real and imag complex elements.
    Definition: QuEST.c:1537
    +
    void phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Shift the phase between and of a single qubit by a given angle.
    Definition: QuEST.c:487
    @ PRODUCT
    Definition: QuEST.h:233
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:341
    -
    void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled not (single control, single target) gate, also known as the c-X,...
    Definition: QuEST.c:525
    +
    void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled not (single control, single target) gate, also known as the c-X,...
    Definition: QuEST.c:524
    qreal real[2][2]
    Definition: QuEST.h:139
    -
    long long int getNumAmps(Qureg qureg)
    Returns the number of complex amplitudes in a state-vector qureg.
    Definition: QuEST.c:899
    -
    void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:779
    +
    long long int getNumAmps(Qureg qureg)
    Returns the number of complex amplitudes in a state-vector qureg.
    Definition: QuEST.c:912
    +
    void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:778
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:302
    -
    void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
    Definition: QuEST.c:1535
    +
    void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
    Definition: QuEST.c:1550
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    -
    void pauliX(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
    Definition: QuEST.c:433
    +
    void pauliX(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
    Definition: QuEST.c:432
    Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
    Create a new Qureg which is an exact clone of the passed qureg, which can be either a state-vector or...
    Definition: QuEST.c:64
    #define PREPARE_TEST(qureg, ref)
    Prepares a density matrix in the debug state, and the reference QMatrix.
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    -
    qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
    Computes the expected value of a sum of products of Pauli operators.
    Definition: QuEST.c:1197
    -
    void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:270
    +
    qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
    Computes the expected value of a sum of products of Pauli operators.
    Definition: QuEST.c:1210
    +
    void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:269
    ComplexMatrix2 toComplexMatrix2(QMatrix qm)
    Returns a ComplexMatrix2 copy of QMatix qm.
    Definition: utilities.cpp:1021
    -
    void applyFullQFT(Qureg qureg)
    Applies the quantum Fourier transform (QFT) to the entirety of qureg.
    Definition: QuEST.c:877
    +
    void applyFullQFT(Qureg qureg)
    Applies the quantum Fourier transform (QFT) to the entirety of qureg.
    Definition: QuEST.c:876
    int numQubits
    The number of qubits informing the Hilbert dimension of the Hamiltonian.
    Definition: QuEST.h:287
    Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
    Definition: utilities.cpp:1488
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:327
    @@ -14371,51 +14553,51 @@

    @ SCALED_DISTANCE
    Definition: QuEST.h:234
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:308
    qreal real
    Definition: QuEST.h:105
    -
    void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
    Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
    Definition: QuEST.c:999
    +
    void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
    Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
    Definition: QuEST.c:1012
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1399
    +
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1414
    QMatrix getPureDensityMatrix(QVector state)
    Returns a density matrix initialised into the given pure state.
    Definition: utilities.cpp:507
    -
    void tGate(Qureg qureg, int targetQubit)
    Apply the single-qubit T gate.
    Definition: QuEST.c:477
    -
    void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
    Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
    Definition: QuEST.c:653
    +
    void tGate(Qureg qureg, int targetQubit)
    Apply the single-qubit T gate.
    Definition: QuEST.c:476
    +
    void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
    Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
    Definition: QuEST.c:652
    qreal imag
    Definition: QuEST.h:106
    void deleteFilesWithPrefixSynch(char *prefix)
    Deletes all files with filename starting with prefix.
    Definition: utilities.cpp:1375
    QMatrix getRandomDensityMatrix(int numQb)
    Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed sta...
    Definition: utilities.cpp:490
    QMatrix getExponentialOfDiagonalMatrix(QMatrix a)
    Returns the matrix exponential of a diagonal, square, complex matrix.
    Definition: utilities.cpp:197
    -
    void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
    Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
    Definition: QuEST.c:832
    +
    void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
    Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
    Definition: QuEST.c:831
    @ SCALED_INVERSE_SHIFTED_DISTANCE
    Definition: QuEST.h:234
    -
    void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
    Mixes a density matrix qureg to induce general single-qubit Pauli noise.
    Definition: QuEST.c:1290
    +
    void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
    Mixes a density matrix qureg to induce general single-qubit Pauli noise.
    Definition: QuEST.c:1303
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:153
    -
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:177
    +
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:176
    Represents one complex number.
    Definition: QuEST.h:103
    -
    void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general 2-by-2 matrix, which may be non-unitary.
    Definition: QuEST.c:1071
    +
    void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general 2-by-2 matrix, which may be non-unitary.
    Definition: QuEST.c:1084
    #define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
    Prepares the needed data structures for unit testing some operators.
    -
    void rotateZ(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
    Definition: QuEST.c:210
    +
    void rotateZ(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
    Definition: QuEST.c:209
    QVector getRandomQVector(int dim)
    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
    Definition: utilities.cpp:435
    @ SCALED_NORM
    Definition: QuEST.h:232
    @ SCALED_INVERSE_PRODUCT
    Definition: QuEST.h:233
    -
    void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general multiple-control single-target unitary, which can include a global phase factor.
    Definition: QuEST.c:374
    +
    void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general multiple-control single-target unitary, which can include a global phase factor.
    Definition: QuEST.c:373
    void applyReferenceMatrix(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of left-multiplying the multi-target operator matrix...
    Definition: utilities.cpp:841
    void initZeroState(Qureg qureg)
    Initialise qureg into the zero state.
    Definition: QuEST.c:113
    QVector getDFT(QVector in)
    Returns the discrete fourier transform of vector in.
    Definition: utilities.cpp:652
    -
    qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
    Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
    Definition: QuEST.c:1145
    +
    qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
    Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
    Definition: QuEST.c:1158
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:398
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
    Definition: QuEST.c:50
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:728
    #define M_PI
    Definition: QuEST_common.c:41
    -
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1057
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1383
    +
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1070
    +
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1398
    Catch::Generators::GeneratorWrapper< int * > bitsets(int numBits)
    Returns a Catch2 generator of every numBits-length bit-set, in increasing lexographic order,...
    Definition: utilities.cpp:1557
    qcomp getRandomComplex()
    Returns a random complex number within the square closing (-1-i) and (1+i), from a distribution unifo...
    Definition: utilities.cpp:431
    void initPlusState(Qureg qureg)
    Initialise qureg into the plus state.
    Definition: QuEST.c:125
    -
    qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
    Computes the expected value of a product of Pauli operators.
    Definition: QuEST.c:1188
    -
    void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
    Definition: QuEST.c:418
    -
    void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
    Definition: QuEST.c:389
    -
    void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Performs a sqrt SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:640
    +
    qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
    Computes the expected value of a product of Pauli operators.
    Definition: QuEST.c:1201
    +
    void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
    Definition: QuEST.c:417
    +
    void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
    Definition: QuEST.c:388
    +
    void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Performs a sqrt SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:639
    bitEncoding
    Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
    Definition: QuEST.h:269
    -
    void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
    Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
    Definition: QuEST.c:1321
    -
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1503
    +
    void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
    Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
    Definition: QuEST.c:1334
    +
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1518
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:137
    -
    void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:233
    +
    void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:232
    @ SCALED_INVERSE_NORM
    Definition: QuEST.h:232
    diff --git a/docs/index.html b/docs/index.html index 6d5dda27d..8393c3fce 100644 --- a/docs/index.html +++ b/docs/index.html @@ -27,7 +27,7 @@ @@ -57,7 +57,7 @@

    The QuEST logo

    GitHub release Doc unit tests MIT license

    The Quantum Exact Simulation Toolkit is a high performance simulator of quantum circuits, state-vectors and density matrices. QuEST uses multithreading, GPU acceleration and distribution to run lightning first on laptops, desktops and networked supercomputers. QuEST just works; it is stand-alone, requires no installation, and trivial to compile and getting running.

    -

    Languages Languages Platforms Platforms Platforms

    +

    Languages Languages OS OS OS Platforms Platforms Platforms

    QuEST is developed by the QTechTheory group at the University of Oxford, and these authors. To learn more:

    • see the tutorial
    • view the documentation
    • @@ -116,8 +116,8 @@

    • :ballot_box_with_check:   QASM output to verify simulated circuits
    • -
    • :ballot_box_with_check:   direct access to amplitudes for rapid custom modification of the quantum state
      -
    • +
    • :ballot_box_with_check:   direct access to amplitudes for rapid custom modification of the quantum state
    • +
    • :ballot_box_with_check:   native compilation on MacOS, Linux and Windows, through Clang, GNU, Intel, and MSVC compilers

    @@ -167,7 +167,10 @@


    -

    Windows users should install Build Tools for Visual Studio, CMake and MinGW-w64, and run the above commmands in the Developer Command Prompt for VS, with alternate cmake argument

    cmake .. -G "MinGW Makefiles"
    +

    Windows users should install Build Tools for Visual Studio, and CMake, and run the above commmands in the Developer Command Prompt for VS, though using build commands

    cmake .. -G "NMake Makefiles"
    +
    nmake
    +

    If using MSVC and NMake in this way fails, users can forego GPU acceleration, download MinGW-w64, and compile via

    cmake .. -G "MinGW Makefiles"
    +
    make


    @@ -199,21 +202,21 @@

    Represents a 3-vector of real numbers.
    Definition: QuEST.h:198
    -
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:221
    -
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:602
    -
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1259
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    +
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:220
    +
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:601
    +
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1272
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    qreal z
    Definition: QuEST.h:200
    -
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:1153
    -
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:349
    +
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:1166
    +
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:348
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    -
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:1206
    -
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:331
    +
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:1219
    +
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:330
    qreal y
    Definition: QuEST.h:200
    qreal x
    Definition: QuEST.h:200
    qreal real[2][2]
    Definition: QuEST.h:139
    -
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:177
    -
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1057
    +
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:176
    +
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1070
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:137
    diff --git a/docs/main_8cpp.html b/docs/main_8cpp.html index d316ece6c..73665a7e6 100644 --- a/docs/main_8cpp.html +++ b/docs/main_8cpp.html @@ -27,7 +27,7 @@ @@ -150,7 +150,7 @@

    38  return result;
    39 }
    -

    References createQuESTEnv(), destroyQuESTEnv(), and QUEST_ENV.

    +

    References createQuESTEnv(), destroyQuESTEnv(), and QUEST_ENV.

    @@ -177,7 +177,7 @@

    void destroyQuESTEnv(QuESTEnv env)
    Destroy the QuEST environment.
    +
    void destroyQuESTEnv(QuESTEnv env)
    Destroy the QuEST environment.
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    QuESTEnv createQuESTEnv(void)
    Create the QuEST execution environment.
    diff --git a/docs/main_8cpp_source.html b/docs/main_8cpp_source.html index 4b8a8b41d..7d8474e4f 100644 --- a/docs/main_8cpp_source.html +++ b/docs/main_8cpp_source.html @@ -27,7 +27,7 @@ @@ -77,10 +77,10 @@
    38  return result;
    39 }
    -
    void destroyQuESTEnv(QuESTEnv env)
    Destroy the QuEST environment.
    +
    void destroyQuESTEnv(QuESTEnv env)
    Destroy the QuEST environment.
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:361
    +
    Information about the environment the program is running in.
    Definition: QuEST.h:362
    void invalidQuESTInputError(const char *errMsg, const char *errFunc)
    Redefinition of QuEST_validation's invalidQuESTInputError function, called when a user passes an inco...
    Definition: main.cpp:27
    QuESTEnv createQuESTEnv(void)
    Create the QuEST execution environment.
    int main(int argc, char *argv[])
    Explicit declaration of main to create (destroy) the QuESTEnv before (after) invoking the Catch unit ...
    Definition: main.cpp:34
    diff --git a/docs/modules.html b/docs/modules.html index b4e2246a5..239b78beb 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -27,7 +27,7 @@ diff --git a/docs/mt19937ar_8c.html b/docs/mt19937ar_8c.html index 1402b2452..8ecbec27e 100644 --- a/docs/mt19937ar_8c.html +++ b/docs/mt19937ar_8c.html @@ -27,7 +27,7 @@ @@ -430,7 +430,7 @@

    References init_genrand(), mt, and N.

    -

    Referenced by seedQuEST(), and seedQuESTDefault().

    +

    Referenced by seedQuEST().

    diff --git a/docs/mt19937ar_8c_source.html b/docs/mt19937ar_8c_source.html index 644ecad6f..998e03e49 100644 --- a/docs/mt19937ar_8c_source.html +++ b/docs/mt19937ar_8c_source.html @@ -27,7 +27,7 @@ diff --git a/docs/mt19937ar_8h.html b/docs/mt19937ar_8h.html index 27a951bee..6335d760b 100644 --- a/docs/mt19937ar_8h.html +++ b/docs/mt19937ar_8h.html @@ -27,7 +27,7 @@ @@ -238,7 +238,7 @@

    References init_genrand(), mt, and N.

    -

    Referenced by seedQuEST(), and seedQuESTDefault().

    +

    Referenced by seedQuEST().

    diff --git a/docs/mt19937ar_8h_source.html b/docs/mt19937ar_8h_source.html index f72b3350f..7865e0c13 100644 --- a/docs/mt19937ar_8h_source.html +++ b/docs/mt19937ar_8h_source.html @@ -27,7 +27,7 @@ diff --git a/docs/pages.html b/docs/pages.html index 663ab5696..a2a335f38 100644 --- a/docs/pages.html +++ b/docs/pages.html @@ -27,7 +27,7 @@ diff --git a/docs/structComplex.html b/docs/structComplex.html index 03c3a1ba9..22e48c9e4 100644 --- a/docs/structComplex.html +++ b/docs/structComplex.html @@ -27,7 +27,7 @@ @@ -89,7 +89,7 @@

    Definition at line 106 of file QuEST.h.

    -

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), getAmp(), getComplexPairAndPhaseFromUnitary(), getComplexPairFromRotation(), getConjugateScalar(), getRotAngle(), getZYZRotAnglesFromComplexPair(), isComplexPairUnitary(), isComplexUnit(), statevec_calcExpecDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), statevec_calcFidelity(), statevec_calcInnerProduct(), statevec_calcInnerProductLocal(), statevec_compactUnitaryDistributed(), statevec_compactUnitaryKernel(), statevec_compactUnitaryLocal(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledRotateAroundAxisConj(), statevec_controlledUnitaryDistributed(), statevec_multiControlledUnitaryDistributed(), statevec_multiRotatePauli(), statevec_pauliZ(), statevec_phaseShift(), statevec_phaseShiftByTerm(), statevec_rotateAroundAxisConj(), statevec_setWeightedQureg(), statevec_setWeightedQuregKernel(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), statevec_tGateConj(), statevec_unitaryDistributed(), TEST_CASE(), and toQMatrix().

    +

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), getAmp(), getComplexPairAndPhaseFromUnitary(), getComplexPairFromRotation(), getConjugateScalar(), getRotAngle(), getZYZRotAnglesFromComplexPair(), isComplexPairUnitary(), isComplexUnit(), statevec_calcExpecDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), statevec_calcFidelity(), statevec_calcInnerProduct(), statevec_calcInnerProductLocal(), statevec_compactUnitaryDistributed(), statevec_compactUnitaryKernel(), statevec_compactUnitaryLocal(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledRotateAroundAxisConj(), statevec_controlledUnitaryDistributed(), statevec_multiControlledUnitaryDistributed(), statevec_multiRotatePauli(), statevec_pauliZ(), statevec_phaseShift(), statevec_phaseShiftByTerm(), statevec_rotateAroundAxisConj(), statevec_setWeightedQureg(), statevec_setWeightedQuregKernel(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), statevec_tGateConj(), statevec_unitaryDistributed(), TEST_CASE(), and toQMatrix().

    @@ -107,7 +107,7 @@

    Definition at line 105 of file QuEST.h.

    -

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), getAmp(), getComplexPairAndPhaseFromUnitary(), getComplexPairFromRotation(), getConjugateScalar(), getDensityAmp(), getRotAngle(), getRotAngleFromUnitaryMatrix(), getZYZRotAnglesFromComplexPair(), isComplexPairUnitary(), isComplexUnit(), statevec_applyPauliSum(), statevec_calcExpecDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), statevec_calcExpecPauliProd(), statevec_calcFidelity(), statevec_calcInnerProduct(), statevec_calcInnerProductLocal(), statevec_compactUnitaryDistributed(), statevec_compactUnitaryKernel(), statevec_compactUnitaryLocal(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledUnitaryDistributed(), statevec_multiControlledUnitaryDistributed(), statevec_multiRotatePauli(), statevec_pauliZ(), statevec_phaseShift(), statevec_phaseShiftByTerm(), statevec_setWeightedQureg(), statevec_setWeightedQuregKernel(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), statevec_tGateConj(), statevec_unitaryDistributed(), TEST_CASE(), and toQMatrix().

    +

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), getAmp(), getComplexPairAndPhaseFromUnitary(), getComplexPairFromRotation(), getConjugateScalar(), getDensityAmp(), getRotAngle(), getRotAngleFromUnitaryMatrix(), getZYZRotAnglesFromComplexPair(), isComplexPairUnitary(), isComplexUnit(), statevec_applyPauliSum(), statevec_calcExpecDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), statevec_calcExpecPauliProd(), statevec_calcFidelity(), statevec_calcInnerProduct(), statevec_calcInnerProductLocal(), statevec_compactUnitaryDistributed(), statevec_compactUnitaryKernel(), statevec_compactUnitaryLocal(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledUnitaryDistributed(), statevec_multiControlledUnitaryDistributed(), statevec_multiRotatePauli(), statevec_pauliZ(), statevec_phaseShift(), statevec_phaseShiftByTerm(), statevec_setWeightedQureg(), statevec_setWeightedQuregKernel(), statevec_sGate(), statevec_sGateConj(), statevec_tGate(), statevec_tGateConj(), statevec_unitaryDistributed(), TEST_CASE(), and toQMatrix().

    diff --git a/docs/structComplexMatrix2.html b/docs/structComplexMatrix2.html index a05fdfaba..0d5ad3492 100644 --- a/docs/structComplexMatrix2.html +++ b/docs/structComplexMatrix2.html @@ -27,7 +27,7 @@ @@ -105,7 +105,7 @@

    Definition at line 140 of file QuEST.h.

    -

    Referenced by densmatr_mixPauli(), getComplexPairAndPhaseFromUnitary(), getRotAngleFromUnitaryMatrix(), statevec_controlledUnitaryLocal(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledUnitaryLocal(), and statevec_unitaryLocal().

    +

    Referenced by densmatr_mixPauli(), getComplexPairAndPhaseFromUnitary(), getRotAngleFromUnitaryMatrix(), statevec_controlledUnitaryLocal(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledUnitaryLocal(), and statevec_unitaryLocal().

    @@ -123,7 +123,7 @@

    Definition at line 139 of file QuEST.h.

    -

    Referenced by densmatr_mixPauli(), getComplexPairAndPhaseFromUnitary(), getRotAngleFromUnitaryMatrix(), statevec_controlledUnitaryLocal(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledUnitaryLocal(), statevec_unitaryLocal(), and TEST_CASE().

    +

    Referenced by densmatr_mixPauli(), getComplexPairAndPhaseFromUnitary(), getRotAngleFromUnitaryMatrix(), statevec_controlledUnitaryLocal(), statevec_multiControlledMultiRotatePauli(), statevec_multiControlledUnitaryLocal(), statevec_unitaryLocal(), and TEST_CASE().

    diff --git a/docs/structComplexMatrix4.html b/docs/structComplexMatrix4.html index 7f9583ccc..38bd97cb3 100644 --- a/docs/structComplexMatrix4.html +++ b/docs/structComplexMatrix4.html @@ -27,7 +27,7 @@ @@ -106,7 +106,7 @@

    Definition at line 178 of file QuEST.h.

    -

    Referenced by statevec_multiControlledTwoQubitUnitaryLocal(), statevec_sqrtSwapGate(), and statevec_sqrtSwapGateConj().

    +

    Referenced by statevec_multiControlledTwoQubitUnitaryLocal(), statevec_sqrtSwapGate(), and statevec_sqrtSwapGateConj().

    @@ -124,7 +124,7 @@

    Definition at line 177 of file QuEST.h.

    -

    Referenced by statevec_multiControlledTwoQubitUnitaryLocal(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and TEST_CASE().

    +

    Referenced by statevec_multiControlledTwoQubitUnitaryLocal(), statevec_sqrtSwapGate(), statevec_sqrtSwapGateConj(), and TEST_CASE().

    diff --git a/docs/structComplexMatrixN.html b/docs/structComplexMatrixN.html index 9092800d7..7785fec63 100644 --- a/docs/structComplexMatrixN.html +++ b/docs/structComplexMatrixN.html @@ -27,7 +27,7 @@ @@ -91,7 +91,7 @@

    Definition at line 190 of file QuEST.h.

    -

    Referenced by bindArraysToStackComplexMatrixN(), createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryLocal(), TEST_CASE(), toQMatrix(), and validateMatrixInit().

    +

    Referenced by bindArraysToStackComplexMatrixN(), createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryLocal(), TEST_CASE(), toQMatrix(), and validateMatrixInit().

    @@ -109,7 +109,7 @@

    Definition at line 188 of file QuEST.h.

    -

    Referenced by bindArraysToStackComplexMatrixN(), createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), isCompletelyPositiveMapN(), isMatrixNUnitary(), populateKrausSuperOperatorN(), setConjugateMatrixN(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryLocal(), toComplexMatrixN(), toQMatrix(), and validateMultiQubitMatrix().

    +

    Referenced by bindArraysToStackComplexMatrixN(), createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), isCompletelyPositiveMapN(), isMatrixNUnitary(), populateKrausSuperOperatorN(), setConjugateMatrixN(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryLocal(), toComplexMatrixN(), toQMatrix(), and validateMultiQubitMatrix().

    @@ -127,7 +127,7 @@

    Definition at line 189 of file QuEST.h.

    -

    Referenced by bindArraysToStackComplexMatrixN(), createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryLocal(), TEST_CASE(), toQMatrix(), and validateMatrixInit().

    +

    Referenced by bindArraysToStackComplexMatrixN(), createComplexMatrixN(), destroyComplexMatrixN(), initComplexMatrixN(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryLocal(), TEST_CASE(), toQMatrix(), and validateMatrixInit().

    diff --git a/docs/structDiagonalOp.html b/docs/structDiagonalOp.html index e913eacb5..c3e83b504 100644 --- a/docs/structDiagonalOp.html +++ b/docs/structDiagonalOp.html @@ -27,7 +27,7 @@ @@ -109,7 +109,7 @@

    Definition at line 306 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_setDiagonalOpElems(), and TEST_CASE().

    +

    Referenced by agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_setDiagonalOpElems(), and TEST_CASE().

    @@ -129,7 +129,7 @@

    Definition at line 312 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), agnostic_destroyDiagonalOp(), agnostic_initDiagonalOpFromPauliHamilKernel(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), densmatr_applyDiagonalOpKernel(), densmatr_calcExpecDiagonalOp(), statevec_applyDiagonalOpKernel(), and statevec_calcExpecDiagonalOp().

    +

    Referenced by agnostic_createDiagonalOp(), agnostic_destroyDiagonalOp(), agnostic_initDiagonalOpFromPauliHamilKernel(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), densmatr_applyDiagonalOpKernel(), densmatr_calcExpecDiagonalOp(), statevec_applyDiagonalOpKernel(), and statevec_calcExpecDiagonalOp().

    @@ -149,7 +149,7 @@

    Definition at line 310 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), agnostic_destroyDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), copyDiagOpIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), statevec_applyDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), TEST_CASE(), toQVector(), and validateDiagOpInit().

    +

    Referenced by agnostic_createDiagonalOp(), agnostic_destroyDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), copyDiagOpIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), statevec_applyDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), TEST_CASE(), toQVector(), and validateDiagOpInit().

    @@ -169,7 +169,7 @@

    Definition at line 304 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), and TEST_CASE().

    +

    Referenced by agnostic_createDiagonalOp(), and TEST_CASE().

    @@ -189,7 +189,7 @@

    Definition at line 302 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_initDiagonalOpFromPauliHamilKernel(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), copyDiagOpIntoMatrixPairState(), TEST_CASE(), and toQVector().

    +

    Referenced by agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_initDiagonalOpFromPauliHamilKernel(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), copyDiagOpIntoMatrixPairState(), TEST_CASE(), and toQVector().

    @@ -209,7 +209,7 @@

    Definition at line 300 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_initDiagonalOpFromPauliHamilKernel(), densmatr_applyDiagonalOpKernel(), densmatr_applyDiagonalOpLocal(), densmatr_calcExpecDiagonalOp(), initDiagonalOp(), TEST_CASE(), toQMatrix(), toQVector(), validateDiagonalOp(), validateDiagPauliHamil(), and validateNumElems().

    +

    Referenced by agnostic_createDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_initDiagonalOpFromPauliHamilKernel(), densmatr_applyDiagonalOpKernel(), densmatr_applyDiagonalOpLocal(), densmatr_calcExpecDiagonalOp(), initDiagonalOp(), TEST_CASE(), toQMatrix(), toQVector(), validateDiagonalOp(), validateDiagPauliHamil(), and validateNumElems().

    @@ -229,7 +229,7 @@

    Definition at line 308 of file QuEST.h.

    -

    Referenced by agnostic_createDiagonalOp(), agnostic_destroyDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), copyDiagOpIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), statevec_applyDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), TEST_CASE(), toQVector(), and validateDiagOpInit().

    +

    Referenced by agnostic_createDiagonalOp(), agnostic_destroyDiagonalOp(), agnostic_initDiagonalOpFromPauliHamil(), agnostic_setDiagonalOpElems(), agnostic_syncDiagonalOp(), copyDiagOpIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), statevec_applyDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), TEST_CASE(), toQVector(), and validateDiagOpInit().

    diff --git a/docs/structPauliHamil.html b/docs/structPauliHamil.html index d97360c77..b2badae5a 100644 --- a/docs/structPauliHamil.html +++ b/docs/structPauliHamil.html @@ -27,7 +27,7 @@ @@ -99,7 +99,7 @@

    Definition at line 287 of file QuEST.h.

    -

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), createDiagonalOpFromPauliHamilFile(), createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), toQMatrix(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), validateMatchingQuregPauliHamilDims(), and validatePauliHamil().

    +

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), createDiagonalOpFromPauliHamilFile(), createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), toQMatrix(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), validateMatchingQuregPauliHamilDims(), and validatePauliHamil().

    @@ -119,7 +119,7 @@

    Definition at line 285 of file QuEST.h.

    -

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), applyPauliHamil(), calcExpecPauliHamil(), createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), toQMatrix(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), and validatePauliHamil().

    +

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), applyPauliHamil(), calcExpecPauliHamil(), createPauliHamil(), initDiagonalOpFromPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), toQMatrix(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), and validatePauliHamil().

    @@ -140,7 +140,7 @@

    Definition at line 281 of file QuEST.h.

    -

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), applyPauliHamil(), calcExpecPauliHamil(), createPauliHamil(), createPauliHamilFromFile(), destroyPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), toQMatrix(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), and validatePauliHamil().

    +

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), applyPauliHamil(), calcExpecPauliHamil(), createPauliHamil(), createPauliHamilFromFile(), destroyPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), toQMatrix(), validateDiagPauliHamil(), validateDiagPauliHamilFromFile(), and validatePauliHamil().

    @@ -160,7 +160,7 @@

    Definition at line 283 of file QuEST.h.

    -

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), applyPauliHamil(), calcExpecPauliHamil(), createPauliHamil(), createPauliHamilFromFile(), destroyPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), and toQMatrix().

    +

    Referenced by agnostic_initDiagonalOpFromPauliHamil(), applyExponentiatedPauliHamil(), applyPauliHamil(), calcExpecPauliHamil(), createPauliHamil(), createPauliHamilFromFile(), destroyPauliHamil(), initPauliHamil(), reportPauliHamil(), setRandomDiagPauliHamil(), setRandomPauliSum(), TEST_CASE(), and toQMatrix().

    diff --git a/docs/structQuESTEnv.html b/docs/structQuESTEnv.html index 8669dfd9e..e78ac7d55 100644 --- a/docs/structQuESTEnv.html +++ b/docs/structQuESTEnv.html @@ -27,7 +27,7 @@ @@ -66,15 +66,21 @@ Data Fields

    int numRanks   +int numSeeds +  int rank   +unsigned long int * seeds

    Detailed Description

    Information about the environment the program is running in.

    In practice, this holds info about MPI ranks and helps to hide MPI initialization code

    -
    Author
    Ania Brown
    +
    Author
    Ania Brown
    +
    +Tyson Jones (seeding)
    -

    Definition at line 361 of file QuEST.h.

    +

    Definition at line 362 of file QuEST.h.

    Field Documentation

    ◆ numRanks

    @@ -88,9 +94,27 @@

    -

    Definition at line 364 of file QuEST.h.

    +

    Definition at line 365 of file QuEST.h.

    + +

    Referenced by agnostic_createDiagonalOp(), createDensityQureg(), createDiagonalOp(), createDiagonalOpFromPauliHamilFile(), createQuESTEnv(), createQureg(), getEnvironmentString(), reportQuESTEnv(), statevec_createQureg(), statevec_destroyQureg(), and TEST_CASE().

    + + + + +

    ◆ numSeeds

    + + @@ -106,9 +130,27 @@

    -

    Definition at line 363 of file QuEST.h.

    +

    Definition at line 364 of file QuEST.h.

    + +

    Referenced by agnostic_createDiagonalOp(), createQuESTEnv(), deleteFilesWithPrefixSynch(), reportQuESTEnv(), statevec_createQureg(), TEST_CASE(), and writeToFileSynch().

    + + + + +

    ◆ seeds

    + +
    +
    + + + + +
    unsigned long int* QuESTEnv::seeds
    +
    diff --git a/docs/structQureg.html b/docs/structQureg.html index a927307ca..ce05ba4d1 100644 --- a/docs/structQureg.html +++ b/docs/structQureg.html @@ -27,7 +27,7 @@ @@ -128,7 +128,7 @@

    Definition at line 336 of file QuEST.h.

    -

    Referenced by areEqual(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyDiagOpIntoMatrixPairState(), copyVecIntoMatrixPairState(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelityLocal(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcTotalProb(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPureStateLocal(), densmatr_mixDamping(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), getGlobalIndOfOddParityInChunk(), reportQuregParams(), reportState(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyPhaseFuncOverrides(), statevec_calcProbOfAllOutcomesLocal(), statevec_calcProbOfOutcome(), statevec_collapseToKnownProbOutcome(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNot(), statevec_controlledNotDistributed(), statevec_controlledNotLocal(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledPauliYDistributed(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseShift(), statevec_controlledUnitary(), statevec_controlledUnitaryDistributed(), statevec_controlledUnitaryLocal(), statevec_createQureg(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamard(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNotDistributed(), statevec_multiControlledMultiQubitNotLocal(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledMultiRotateZ(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_multiControlledUnitary(), statevec_multiControlledUnitaryDistributed(), statevec_multiControlledUnitaryLocal(), statevec_multiRotateZ(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_phaseShiftByTerm(), statevec_reportStateToScreen(), statevec_setAmps(), statevec_swapQubitAmpsDistributed(), statevec_unitary(), and toQureg().

    +

    Referenced by areEqual(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyDiagOpIntoMatrixPairState(), copyVecIntoMatrixPairState(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelityLocal(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcTotalProb(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPureStateLocal(), densmatr_mixDamping(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), getGlobalIndOfOddParityInChunk(), reportQuregParams(), reportState(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyPhaseFuncOverrides(), statevec_calcProbOfAllOutcomesLocal(), statevec_calcProbOfOutcome(), statevec_collapseToKnownProbOutcome(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNot(), statevec_controlledNotDistributed(), statevec_controlledNotLocal(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledPauliYDistributed(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseShift(), statevec_controlledUnitary(), statevec_controlledUnitaryDistributed(), statevec_controlledUnitaryLocal(), statevec_createQureg(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamard(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNotDistributed(), statevec_multiControlledMultiQubitNotLocal(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledMultiRotateZ(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_multiControlledUnitary(), statevec_multiControlledUnitaryDistributed(), statevec_multiControlledUnitaryLocal(), statevec_multiRotateZ(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_phaseShiftByTerm(), statevec_reportStateToScreen(), statevec_setAmps(), statevec_swapQubitAmpsDistributed(), statevec_unitary(), and toQureg().

    @@ -148,7 +148,7 @@

    Definition at line 346 of file QuEST.h.

    -

    Referenced by copyStateFromGPU(), copyStateToGPU(), densmatr_applyDiagonalOpKernel(), densmatr_calcExpecDiagonalOp(), densmatr_calcFidelityKernel(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProductKernel(), densmatr_calcProbOfAllOutcomesKernel(), densmatr_calcPurity(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroKernel(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_initPureState(), densmatr_mixDamping(), densmatr_mixDensityMatrixKernel(), densmatr_mixDepolarising(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_oneQubitDegradeOffDiagonal(), statevec_applyDiagonalOpKernel(), statevec_applyMultiVarPhaseFuncOverridesKernel(), statevec_applyParamNamedPhaseFuncOverridesKernel(), statevec_applyPhaseFuncOverridesKernel(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_calcProbOfAllOutcomesKernel(), statevec_cloneQureg(), statevec_collapseToKnownProbOutcomeKernel(), statevec_compactUnitaryKernel(), statevec_controlledCompactUnitaryKernel(), statevec_controlledNotKernel(), statevec_controlledPauliYKernel(), statevec_controlledPhaseFlipKernel(), statevec_controlledPhaseShiftKernel(), statevec_controlledUnitaryKernel(), statevec_createQureg(), statevec_destroyQureg(), statevec_findProbabilityOfZeroKernel(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamardKernel(), statevec_initBlankState(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initPlusState(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNotKernel(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiRotateZKernel(), statevec_multiControlledPhaseFlipKernel(), statevec_multiControlledPhaseShiftKernel(), statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledUnitaryKernel(), statevec_multiRotateZKernel(), statevec_pauliXKernel(), statevec_pauliYKernel(), statevec_phaseShiftByTermKernel(), statevec_setAmps(), statevec_setWeightedQuregKernel(), statevec_swapQubitAmpsKernel(), and statevec_unitaryKernel().

    +

    Referenced by copyStateFromGPU(), copyStateToGPU(), densmatr_applyDiagonalOpKernel(), densmatr_calcExpecDiagonalOp(), densmatr_calcFidelityKernel(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProductKernel(), densmatr_calcProbOfAllOutcomesKernel(), densmatr_calcPurity(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroKernel(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_initPureState(), densmatr_mixDamping(), densmatr_mixDensityMatrixKernel(), densmatr_mixDepolarising(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_oneQubitDegradeOffDiagonal(), statevec_applyDiagonalOpKernel(), statevec_applyMultiVarPhaseFuncOverridesKernel(), statevec_applyParamNamedPhaseFuncOverridesKernel(), statevec_applyPhaseFuncOverridesKernel(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_calcProbOfAllOutcomesKernel(), statevec_cloneQureg(), statevec_collapseToKnownProbOutcomeKernel(), statevec_compactUnitaryKernel(), statevec_controlledCompactUnitaryKernel(), statevec_controlledNotKernel(), statevec_controlledPauliYKernel(), statevec_controlledPhaseFlipKernel(), statevec_controlledPhaseShiftKernel(), statevec_controlledUnitaryKernel(), statevec_createQureg(), statevec_destroyQureg(), statevec_findProbabilityOfZeroKernel(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamardKernel(), statevec_initBlankState(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initPlusState(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNotKernel(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiRotateZKernel(), statevec_multiControlledPhaseFlipKernel(), statevec_multiControlledPhaseShiftKernel(), statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledUnitaryKernel(), statevec_multiRotateZKernel(), statevec_pauliXKernel(), statevec_pauliYKernel(), statevec_phaseShiftByTermKernel(), statevec_setAmps(), statevec_setWeightedQuregKernel(), statevec_swapQubitAmpsKernel(), and statevec_unitaryKernel().

    @@ -168,7 +168,7 @@

    Definition at line 348 of file QuEST.h.

    -

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_createQureg(), statevec_destroyQureg(), and statevec_findProbabilityOfZero().

    +

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_createQureg(), statevec_destroyQureg(), and statevec_findProbabilityOfZero().

    @@ -188,7 +188,7 @@

    Definition at line 325 of file QuEST.h.

    -

    Referenced by agnostic_applyQFT(), applyDiagonalOp(), applyExponentiatedPauliHamil(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), applyParamNamedPhaseFuncOverrides(), applyPhaseFunc(), applyPhaseFuncOverrides(), areEqual(), calcExpecDiagonalOp(), calcFidelity(), calcProbOfAllOutcomes(), calcProbOfOutcome(), calcTotalProb(), collapseToOutcome(), compactUnitary(), controlledCompactUnitary(), controlledMultiQubitUnitary(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), controlledPhaseShift(), controlledRotateAroundAxis(), controlledRotateX(), controlledRotateY(), controlledRotateZ(), controlledTwoQubitUnitary(), controlledUnitary(), createCloneQureg(), createDensityQureg(), createQureg(), hadamard(), initClassicalState(), initPlusState(), initPureState(), measure(), measureWithStats(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), multiStateControlledUnitary(), pauliX(), pauliY(), pauliZ(), phaseShift(), rotateAroundAxis(), rotateX(), rotateY(), rotateZ(), sGate(), sqrtSwapGate(), statevec_calcExpecPauliProd(), statevec_createQureg(), swapGate(), TEST_CASE(), tGate(), toQMatrix(), toQureg(), toQVector(), twoQubitUnitary(), unitary(), validateDensityMatrQureg(), validateMatchingQuregTypes(), validateSecondQuregStateVec(), and validateStateVecQureg().

    +

    Referenced by agnostic_applyQFT(), applyDiagonalOp(), applyExponentiatedPauliHamil(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), applyParamNamedPhaseFuncOverrides(), applyPhaseFunc(), applyPhaseFuncOverrides(), applyProjector(), areEqual(), calcExpecDiagonalOp(), calcFidelity(), calcProbOfAllOutcomes(), calcProbOfOutcome(), calcTotalProb(), collapseToOutcome(), compactUnitary(), controlledCompactUnitary(), controlledMultiQubitUnitary(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), controlledPhaseShift(), controlledRotateAroundAxis(), controlledRotateX(), controlledRotateY(), controlledRotateZ(), controlledTwoQubitUnitary(), controlledUnitary(), createCloneQureg(), createDensityQureg(), createQureg(), hadamard(), initClassicalState(), initPlusState(), initPureState(), measure(), measureWithStats(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), multiStateControlledUnitary(), pauliX(), pauliY(), pauliZ(), phaseShift(), rotateAroundAxis(), rotateX(), rotateY(), rotateZ(), sGate(), sqrtSwapGate(), statevec_calcExpecPauliProd(), statevec_createQureg(), swapGate(), TEST_CASE(), tGate(), toQMatrix(), toQureg(), toQVector(), twoQubitUnitary(), unitary(), validateDensityMatrQureg(), validateMatchingQuregTypes(), validateSecondQuregStateVec(), and validateStateVecQureg().

    @@ -208,7 +208,7 @@

    Definition at line 332 of file QuEST.h.

    -

    Referenced by areEqual(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyStateFromGPU(), copyStateToGPU(), copyVecIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_applyDiagonalOpKernel(), densmatr_applyDiagonalOpLocal(), densmatr_calcExpecDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelityLocal(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), densmatr_calcInnerProductLocal(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcPurity(), densmatr_calcPurityLocal(), densmatr_calcTotalProb(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_initPureState(), densmatr_initPureStateLocal(), densmatr_mixDamping(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDensityMatrix(), densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), exchangePairStateVectorHalves(), exchangeStateVectors(), getChunkIdFromIndex(), getGlobalIndOfOddParityInChunk(), reportState(), statevec_applyDiagonalOp(), statevec_applyDiagonalOpKernel(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyMultiVarPhaseFuncOverridesKernel(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverridesKernel(), statevec_applyPhaseFuncOverrides(), statevec_applyPhaseFuncOverridesKernel(), statevec_calcExpecDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), statevec_calcInnerProduct(), statevec_calcInnerProductLocal(), statevec_calcProbOfAllOutcomes(), statevec_calcProbOfAllOutcomesLocal(), statevec_calcProbOfOutcome(), statevec_calcTotalProb(), statevec_cloneQureg(), statevec_collapseToKnownProbOutcome(), statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeKernel(), statevec_collapseToKnownProbOutcomeLocal(), statevec_collapseToOutcomeDistributedSetZero(), statevec_compactUnitary(), statevec_compactUnitaryDistributed(), statevec_compactUnitaryKernel(), statevec_compactUnitaryLocal(), statevec_compareStates(), statevec_controlledCompactUnitary(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNot(), statevec_controlledNotDistributed(), statevec_controlledNotKernel(), statevec_controlledNotLocal(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledPauliYDistributed(), statevec_controlledPauliYKernel(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseFlipKernel(), statevec_controlledPhaseShift(), statevec_controlledPhaseShiftKernel(), statevec_controlledUnitary(), statevec_controlledUnitaryDistributed(), statevec_controlledUnitaryKernel(), statevec_controlledUnitaryLocal(), statevec_createQureg(), statevec_destroyQureg(), statevec_findProbabilityOfZero(), statevec_findProbabilityOfZeroDistributed(), statevec_findProbabilityOfZeroKernel(), statevec_findProbabilityOfZeroLocal(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamard(), statevec_hadamardDistributed(), statevec_hadamardKernel(), statevec_hadamardLocal(), statevec_initBlankState(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initPlusState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNotDistributed(), statevec_multiControlledMultiQubitNotKernel(), statevec_multiControlledMultiQubitNotLocal(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledMultiRotateZ(), statevec_multiControlledMultiRotateZKernel(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseFlipKernel(), statevec_multiControlledPhaseShift(), statevec_multiControlledPhaseShiftKernel(), statevec_multiControlledTwoQubitUnitary(), statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_multiControlledUnitary(), statevec_multiControlledUnitaryDistributed(), statevec_multiControlledUnitaryKernel(), statevec_multiControlledUnitaryLocal(), statevec_multiRotateZ(), statevec_multiRotateZKernel(), statevec_pauliX(), statevec_pauliXDistributed(), statevec_pauliXKernel(), statevec_pauliXLocal(), statevec_pauliY(), statevec_pauliYConj(), statevec_pauliYDistributed(), statevec_pauliYKernel(), statevec_pauliYLocal(), statevec_phaseShiftByTerm(), statevec_phaseShiftByTermKernel(), statevec_reportStateToScreen(), statevec_setAmps(), statevec_setWeightedQureg(), statevec_setWeightedQuregKernel(), statevec_swapQubitAmps(), statevec_swapQubitAmpsDistributed(), statevec_swapQubitAmpsKernel(), statevec_swapQubitAmpsLocal(), statevec_unitary(), statevec_unitaryDistributed(), statevec_unitaryKernel(), statevec_unitaryLocal(), TEST_CASE(), toQMatrix(), toQureg(), toQVector(), and validateMultiQubitMatrixFitsInNode().

    +

    Referenced by areEqual(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyStateFromGPU(), copyStateToGPU(), copyVecIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_applyDiagonalOpKernel(), densmatr_applyDiagonalOpLocal(), densmatr_calcExpecDiagonalOp(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelityLocal(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), densmatr_calcInnerProductLocal(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcPurity(), densmatr_calcPurityLocal(), densmatr_calcTotalProb(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_initPureState(), densmatr_initPureStateLocal(), densmatr_mixDamping(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDensityMatrix(), densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), exchangePairStateVectorHalves(), exchangeStateVectors(), getChunkIdFromIndex(), getGlobalIndOfOddParityInChunk(), reportState(), statevec_applyDiagonalOp(), statevec_applyDiagonalOpKernel(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyMultiVarPhaseFuncOverridesKernel(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverridesKernel(), statevec_applyPhaseFuncOverrides(), statevec_applyPhaseFuncOverridesKernel(), statevec_calcExpecDiagonalOp(), statevec_calcExpecDiagonalOpLocal(), statevec_calcInnerProduct(), statevec_calcInnerProductLocal(), statevec_calcProbOfAllOutcomes(), statevec_calcProbOfAllOutcomesLocal(), statevec_calcProbOfOutcome(), statevec_calcTotalProb(), statevec_cloneQureg(), statevec_collapseToKnownProbOutcome(), statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeKernel(), statevec_collapseToKnownProbOutcomeLocal(), statevec_collapseToOutcomeDistributedSetZero(), statevec_compactUnitary(), statevec_compactUnitaryDistributed(), statevec_compactUnitaryKernel(), statevec_compactUnitaryLocal(), statevec_compareStates(), statevec_controlledCompactUnitary(), statevec_controlledCompactUnitaryDistributed(), statevec_controlledCompactUnitaryKernel(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNot(), statevec_controlledNotDistributed(), statevec_controlledNotKernel(), statevec_controlledNotLocal(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledPauliYDistributed(), statevec_controlledPauliYKernel(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseFlipKernel(), statevec_controlledPhaseShift(), statevec_controlledPhaseShiftKernel(), statevec_controlledUnitary(), statevec_controlledUnitaryDistributed(), statevec_controlledUnitaryKernel(), statevec_controlledUnitaryLocal(), statevec_createQureg(), statevec_destroyQureg(), statevec_findProbabilityOfZero(), statevec_findProbabilityOfZeroDistributed(), statevec_findProbabilityOfZeroKernel(), statevec_findProbabilityOfZeroLocal(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamard(), statevec_hadamardDistributed(), statevec_hadamardKernel(), statevec_hadamardLocal(), statevec_initBlankState(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initPlusState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNotDistributed(), statevec_multiControlledMultiQubitNotKernel(), statevec_multiControlledMultiQubitNotLocal(), statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledMultiQubitUnitaryKernel(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledMultiRotateZ(), statevec_multiControlledMultiRotateZKernel(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseFlipKernel(), statevec_multiControlledPhaseShift(), statevec_multiControlledPhaseShiftKernel(), statevec_multiControlledTwoQubitUnitary(), statevec_multiControlledTwoQubitUnitaryKernel(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_multiControlledUnitary(), statevec_multiControlledUnitaryDistributed(), statevec_multiControlledUnitaryKernel(), statevec_multiControlledUnitaryLocal(), statevec_multiRotateZ(), statevec_multiRotateZKernel(), statevec_pauliX(), statevec_pauliXDistributed(), statevec_pauliXKernel(), statevec_pauliXLocal(), statevec_pauliY(), statevec_pauliYConj(), statevec_pauliYDistributed(), statevec_pauliYKernel(), statevec_pauliYLocal(), statevec_phaseShiftByTerm(), statevec_phaseShiftByTermKernel(), statevec_reportStateToScreen(), statevec_setAmps(), statevec_setWeightedQureg(), statevec_setWeightedQuregKernel(), statevec_swapQubitAmps(), statevec_swapQubitAmpsDistributed(), statevec_swapQubitAmpsKernel(), statevec_swapQubitAmpsLocal(), statevec_unitary(), statevec_unitaryDistributed(), statevec_unitaryKernel(), statevec_unitaryLocal(), TEST_CASE(), toQMatrix(), toQureg(), toQVector(), and validateMultiQubitMatrixFitsInNode().

    @@ -228,7 +228,7 @@

    Definition at line 334 of file QuEST.h.

    -

    Referenced by areEqual(), densmatr_calcFidelityLocal(), densmatr_calcInnerProduct(), densmatr_initPureStateLocal(), getNumAmps(), initStateFromAmps(), setDensityAmps(), statevec_calcProbOfAllOutcomesKernel(), statevec_createQureg(), statevec_destroyQureg(), TEST_CASE(), toQMatrix(), toQureg(), toQVector(), and validateNumAmps().

    +

    Referenced by areEqual(), densmatr_calcFidelityLocal(), densmatr_calcInnerProduct(), densmatr_initPureStateLocal(), getNumAmps(), initStateFromAmps(), setDensityAmps(), statevec_calcProbOfAllOutcomesKernel(), statevec_createQureg(), statevec_destroyQureg(), TEST_CASE(), toQMatrix(), toQureg(), toQVector(), and validateNumAmps().

    @@ -248,7 +248,7 @@

    Definition at line 338 of file QuEST.h.

    -

    Referenced by copyDiagOpIntoMatrixPairState(), copyVecIntoMatrixPairState(), densmatr_calcExpecDiagonalOp(), densmatr_calcTotalProb(), densmatr_initPureState(), reportQuregParams(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_calcTotalProb(), statevec_createQureg(), statevec_initPlusState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), and statevec_reportStateToScreen().

    +

    Referenced by copyDiagOpIntoMatrixPairState(), copyVecIntoMatrixPairState(), densmatr_calcExpecDiagonalOp(), densmatr_calcTotalProb(), densmatr_initPureState(), reportQuregParams(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_calcTotalProb(), statevec_createQureg(), statevec_initPlusState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), and statevec_reportStateToScreen().

    @@ -268,7 +268,7 @@

    Definition at line 329 of file QuEST.h.

    -

    Referenced by createCloneQureg(), createDensityQureg(), createQureg(), reportQuregParams(), statevec_createQureg(), statevec_destroyQureg(), statevec_reportStateToScreen(), and TEST_CASE().

    +

    Referenced by createCloneQureg(), createDensityQureg(), createQureg(), reportQuregParams(), statevec_createQureg(), statevec_destroyQureg(), statevec_reportStateToScreen(), and TEST_CASE().

    @@ -288,7 +288,7 @@

    Definition at line 327 of file QuEST.h.

    -

    Referenced by agnostic_applyQFT(), applyFullQFT(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), applyParamNamedPhaseFuncOverrides(), applyPauliSum(), applyPhaseFunc(), applyPhaseFuncOverrides(), calcExpecPauliSum(), compactUnitary(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), controlledCompactUnitary(), controlledMultiQubitUnitary(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), controlledPhaseShift(), controlledRotateAroundAxis(), controlledRotateX(), controlledRotateY(), controlledRotateZ(), controlledTwoQubitUnitary(), controlledUnitary(), createCloneQureg(), createDensityQureg(), createQureg(), densmatr_applyKrausSuperoperator(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelity(), densmatr_calcProbOfAllOutcomes(), densmatr_calcProbOfAllOutcomesKernel(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcTotalProb(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZero(), densmatr_findProbabilityOfZeroKernel(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_mixDamping(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), getDensityAmp(), getNumQubits(), hadamard(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), multiStateControlledUnitary(), pauliX(), pauliY(), pauliZ(), phaseShift(), qasm_recordInitClassical(), qasm_setup(), rotateAroundAxis(), rotateX(), rotateY(), rotateZ(), sGate(), sqrtSwapGate(), statevec_applyPauliSum(), statevec_calcExpecPauliSum(), swapGate(), TEST_CASE(), tGate(), toQMatrix(), toQureg(), twoQubitUnitary(), unitary(), validateAmpIndex(), validateControl(), validateDiagonalOp(), validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMultiQubits(), validateNumControls(), validateNumTargets(), validateQubitSubregs(), validateStateIndex(), and validateTarget().

    +

    Referenced by agnostic_applyQFT(), applyFullQFT(), applyMultiVarPhaseFunc(), applyMultiVarPhaseFuncOverrides(), applyNamedPhaseFunc(), applyNamedPhaseFuncOverrides(), applyParamNamedPhaseFunc(), applyParamNamedPhaseFuncOverrides(), applyPauliSum(), applyPhaseFunc(), applyPhaseFuncOverrides(), calcExpecPauliSum(), compactUnitary(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), controlledCompactUnitary(), controlledMultiQubitUnitary(), controlledNot(), controlledPauliY(), controlledPhaseFlip(), controlledPhaseShift(), controlledRotateAroundAxis(), controlledRotateX(), controlledRotateY(), controlledRotateZ(), controlledTwoQubitUnitary(), controlledUnitary(), createCloneQureg(), createDensityQureg(), createQureg(), densmatr_applyKrausSuperoperator(), densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelity(), densmatr_calcProbOfAllOutcomes(), densmatr_calcProbOfAllOutcomesKernel(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcTotalProb(), densmatr_collapseToKnownProbOutcome(), densmatr_findProbabilityOfZero(), densmatr_findProbabilityOfZeroKernel(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_mixDamping(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarising(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), getDensityAmp(), getNumQubits(), hadamard(), multiControlledMultiQubitNot(), multiControlledMultiQubitUnitary(), multiControlledMultiRotatePauli(), multiControlledMultiRotateZ(), multiControlledPhaseFlip(), multiControlledPhaseShift(), multiControlledTwoQubitUnitary(), multiControlledUnitary(), multiQubitNot(), multiQubitUnitary(), multiRotatePauli(), multiRotateZ(), multiStateControlledUnitary(), pauliX(), pauliY(), pauliZ(), phaseShift(), qasm_recordInitClassical(), qasm_setup(), rotateAroundAxis(), rotateX(), rotateY(), rotateZ(), sGate(), sqrtSwapGate(), statevec_applyPauliSum(), statevec_calcExpecPauliSum(), swapGate(), TEST_CASE(), tGate(), toQMatrix(), toQureg(), twoQubitUnitary(), unitary(), validateAmpIndex(), validateControl(), validateDiagonalOp(), validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMultiQubits(), validateNumControls(), validateNumTargets(), validateQubitSubregs(), validateStateIndex(), and validateTarget().

    @@ -308,7 +308,7 @@

    Definition at line 343 of file QuEST.h.

    -

    Referenced by compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyDiagOpIntoMatrixPairState(), copyVecIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_applyDiagonalOpLocal(), densmatr_calcFidelity(), densmatr_calcFidelityLocal(), densmatr_initPureState(), densmatr_initPureStateLocal(), densmatr_mixDampingDistributed(), densmatr_mixDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), exchangePairStateVectorHalves(), exchangeStateVectors(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_createQureg(), statevec_destroyQureg(), statevec_hadamard(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_swapQubitAmpsDistributed(), and statevec_unitary().

    +

    Referenced by compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyDiagOpIntoMatrixPairState(), copyVecIntoMatrixPairState(), densmatr_applyDiagonalOp(), densmatr_applyDiagonalOpLocal(), densmatr_calcFidelity(), densmatr_calcFidelityLocal(), densmatr_initPureState(), densmatr_initPureStateLocal(), densmatr_mixDampingDistributed(), densmatr_mixDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), exchangePairStateVectorHalves(), exchangeStateVectors(), statevec_compactUnitary(), statevec_controlledCompactUnitary(), statevec_controlledNot(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledUnitary(), statevec_createQureg(), statevec_destroyQureg(), statevec_hadamard(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledUnitary(), statevec_pauliX(), statevec_pauliY(), statevec_pauliYConj(), statevec_swapQubitAmpsDistributed(), and statevec_unitary().

    @@ -346,7 +346,7 @@

    Definition at line 348 of file QuEST.h.

    -

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_createQureg(), statevec_destroyQureg(), and statevec_findProbabilityOfZero().

    +

    Referenced by densmatr_calcExpecDiagonalOp(), densmatr_calcFidelity(), densmatr_calcHilbertSchmidtDistance(), densmatr_calcInnerProduct(), densmatr_calcPurity(), densmatr_findProbabilityOfZero(), statevec_calcExpecDiagonalOp(), statevec_calcInnerProduct(), statevec_createQureg(), statevec_destroyQureg(), and statevec_findProbabilityOfZero().

    @@ -366,7 +366,7 @@

    Definition at line 341 of file QuEST.h.

    -

    Referenced by areEqual(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyStateFromGPU(), copyStateToGPU(), copyVecIntoMatrixPairState(), densmatr_applyDiagonalOpLocal(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelity(), densmatr_calcFidelityLocal(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), densmatr_calcInnerProductLocal(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcPurityLocal(), densmatr_calcTotalProb(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_initPureState(), densmatr_initPureStateLocal(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDensityMatrix(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), exchangeStateVectors(), normaliseSomeAmps(), reportState(), statevec_applyDiagonalOp(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyPhaseFuncOverrides(), statevec_calcExpecDiagonalOpLocal(), statevec_calcInnerProductLocal(), statevec_calcProbOfAllOutcomesLocal(), statevec_calcTotalProb(), statevec_cloneQureg(), statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), statevec_collapseToOutcomeDistributedSetZero(), statevec_compactUnitary(), statevec_compactUnitaryLocal(), statevec_compareStates(), statevec_controlledCompactUnitary(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNot(), statevec_controlledNotLocal(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseShift(), statevec_controlledUnitary(), statevec_controlledUnitaryLocal(), statevec_createQureg(), statevec_destroyQureg(), statevec_findProbabilityOfZeroDistributed(), statevec_findProbabilityOfZeroLocal(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamard(), statevec_hadamardLocal(), statevec_initBlankState(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initPlusState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNotLocal(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledMultiRotateZ(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_multiControlledUnitary(), statevec_multiControlledUnitaryLocal(), statevec_multiRotateZ(), statevec_pauliX(), statevec_pauliXLocal(), statevec_pauliY(), statevec_pauliYConj(), statevec_pauliYLocal(), statevec_phaseShiftByTerm(), statevec_reportStateToScreen(), statevec_setAmps(), statevec_setWeightedQureg(), statevec_swapQubitAmpsDistributed(), statevec_swapQubitAmpsLocal(), statevec_unitary(), statevec_unitaryLocal(), TEST_CASE(), toQMatrix(), toQureg(), toQVector(), and zeroSomeAmps().

    +

    Referenced by areEqual(), compressPairVectorForSingleQubitDepolarise(), compressPairVectorForTwoQubitDepolarise(), copyStateFromGPU(), copyStateToGPU(), copyVecIntoMatrixPairState(), densmatr_applyDiagonalOpLocal(), densmatr_calcExpecDiagonalOpLocal(), densmatr_calcFidelity(), densmatr_calcFidelityLocal(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), densmatr_calcInnerProductLocal(), densmatr_calcProbOfAllOutcomesLocal(), densmatr_calcPurityLocal(), densmatr_calcTotalProb(), densmatr_findProbabilityOfZeroLocal(), densmatr_initClassicalState(), densmatr_initPlusState(), densmatr_initPureState(), densmatr_initPureStateLocal(), densmatr_mixDampingDistributed(), densmatr_mixDampingLocal(), densmatr_mixDensityMatrix(), densmatr_mixDepolarisingDistributed(), densmatr_mixDepolarisingLocal(), densmatr_mixTwoQubitDephasing(), densmatr_mixTwoQubitDepolarisingDistributed(), densmatr_mixTwoQubitDepolarisingLocal(), densmatr_mixTwoQubitDepolarisingLocalPart1(), densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(), densmatr_oneQubitDegradeOffDiagonal(), exchangeStateVectors(), normaliseSomeAmps(), reportState(), statevec_applyDiagonalOp(), statevec_applyMultiVarPhaseFuncOverrides(), statevec_applyParamNamedPhaseFuncOverrides(), statevec_applyPhaseFuncOverrides(), statevec_calcExpecDiagonalOpLocal(), statevec_calcInnerProductLocal(), statevec_calcProbOfAllOutcomesLocal(), statevec_calcTotalProb(), statevec_cloneQureg(), statevec_collapseToKnownProbOutcomeDistributedRenorm(), statevec_collapseToKnownProbOutcomeLocal(), statevec_collapseToOutcomeDistributedSetZero(), statevec_compactUnitary(), statevec_compactUnitaryLocal(), statevec_compareStates(), statevec_controlledCompactUnitary(), statevec_controlledCompactUnitaryLocal(), statevec_controlledNot(), statevec_controlledNotLocal(), statevec_controlledPauliY(), statevec_controlledPauliYConj(), statevec_controlledPauliYLocal(), statevec_controlledPhaseFlip(), statevec_controlledPhaseShift(), statevec_controlledUnitary(), statevec_controlledUnitaryLocal(), statevec_createQureg(), statevec_destroyQureg(), statevec_findProbabilityOfZeroDistributed(), statevec_findProbabilityOfZeroLocal(), statevec_getImagAmp(), statevec_getRealAmp(), statevec_hadamard(), statevec_hadamardLocal(), statevec_initBlankState(), statevec_initClassicalState(), statevec_initDebugState(), statevec_initPlusState(), statevec_initStateFromSingleFile(), statevec_initStateOfSingleQubit(), statevec_initZeroState(), statevec_multiControlledMultiQubitNot(), statevec_multiControlledMultiQubitNotLocal(), statevec_multiControlledMultiQubitUnitaryLocal(), statevec_multiControlledMultiRotateZ(), statevec_multiControlledPhaseFlip(), statevec_multiControlledPhaseShift(), statevec_multiControlledTwoQubitUnitaryLocal(), statevec_multiControlledUnitary(), statevec_multiControlledUnitaryLocal(), statevec_multiRotateZ(), statevec_pauliX(), statevec_pauliXLocal(), statevec_pauliY(), statevec_pauliYConj(), statevec_pauliYLocal(), statevec_phaseShiftByTerm(), statevec_reportStateToScreen(), statevec_setAmps(), statevec_setWeightedQureg(), statevec_swapQubitAmpsDistributed(), statevec_swapQubitAmpsLocal(), statevec_unitary(), statevec_unitaryLocal(), TEST_CASE(), toQMatrix(), toQureg(), toQVector(), and zeroSomeAmps().

    diff --git a/docs/structVector.html b/docs/structVector.html index 42ee2b1b5..a4922c356 100644 --- a/docs/structVector.html +++ b/docs/structVector.html @@ -27,7 +27,7 @@ diff --git a/docs/test__calculations_8cpp.html b/docs/test__calculations_8cpp.html index c0938c6f1..677ceb52f 100644 --- a/docs/test__calculations_8cpp.html +++ b/docs/test__calculations_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/test__calculations_8cpp_source.html b/docs/test__calculations_8cpp_source.html index f4e9716f6..03d092b85 100644 --- a/docs/test__calculations_8cpp_source.html +++ b/docs/test__calculations_8cpp_source.html @@ -27,7 +27,7 @@ @@ -1509,7 +1509,7 @@
    1525 
    1526 
    -
    qreal getProbAmp(Qureg qureg, long long int index)
    Get the probability of a state-vector at an index in the full state vector.
    Definition: QuEST.c:919
    +
    qreal getProbAmp(Qureg qureg, long long int index)
    Get the probability of a state-vector at an index in the full state vector.
    Definition: QuEST.c:932
    void initBlankState(Qureg qureg)
    Initialises a qureg to have all-zero-amplitudes.
    Definition: QuEST.c:119
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:304
    @@ -1517,71 +1517,71 @@
    #define fromComplex(comp)
    @ PAULI_Z
    Definition: QuEST.h:96
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    -
    qreal calcTotalProb(Qureg qureg)
    A debugging function which calculates the probability of the qubits in qureg being in any state,...
    Definition: QuEST.c:1130
    -
    void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
    Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
    Definition: QuEST.c:1163
    +
    qreal calcTotalProb(Qureg qureg)
    A debugging function which calculates the probability of the qubits in qureg being in any state,...
    Definition: QuEST.c:1143
    +
    void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
    Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
    Definition: QuEST.c:1176
    @ PAULI_I
    Definition: QuEST.h:96
    -
    Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
    Get an amplitude from a density matrix at a given row and column.
    Definition: QuEST.c:936
    +
    Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
    Get an amplitude from a density matrix at a given row and column.
    Definition: QuEST.c:949
    int getRandomInt(int min, int max)
    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:526
    -
    qreal getImagAmp(Qureg qureg, long long int index)
    Get the imaginary component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:912
    -
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1516
    -
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1509
    +
    qreal getImagAmp(Qureg qureg, long long int index)
    Get the imaginary component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:925
    +
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1531
    +
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1524
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    -
    qreal calcPurity(Qureg qureg)
    Calculates the purity of a density matrix, by the trace of the density matrix squared.
    Definition: QuEST.c:1172
    -
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:1153
    -
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
    Definition: QuEST.c:1178
    +
    qreal calcPurity(Qureg qureg)
    Calculates the purity of a density matrix, by the trace of the density matrix squared.
    Definition: QuEST.c:1185
    +
    qreal calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
    Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
    Definition: QuEST.c:1166
    +
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
    Definition: QuEST.c:1191
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:421
    QMatrix getKetBra(QVector ket, QVector bra)
    Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i...
    Definition: utilities.cpp:169
    -
    Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    Computes the expected value of the diagonal operator op for state qureg.
    Definition: QuEST.c:1215
    +
    Complex calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
    Computes the expected value of the diagonal operator op for state qureg.
    Definition: QuEST.c:1228
    #define qreal
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    void toQureg(Qureg qureg, QVector vec)
    Initialises the state-vector qureg to have the same amplitudes as vec.
    Definition: utilities.cpp:1201
    @ PAULI_X
    Definition: QuEST.h:96
    -
    Complex getAmp(Qureg qureg, long long int index)
    Get the complex amplitude at a given index in the state vector.
    Definition: QuEST.c:926
    -
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:1206
    +
    Complex getAmp(Qureg qureg, long long int index)
    Get the complex amplitude at a given index in the state vector.
    Definition: QuEST.c:939
    +
    qreal calcExpecPauliHamil(Qureg qureg, PauliHamil hamil, Qureg workspace)
    Computes the expected value of qureg under Hermitian operator hamil.
    Definition: QuEST.c:1219
    void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes...
    Definition: utilities.cpp:1229
    -
    qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
    Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
    Definition: QuEST.c:1224
    +
    qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
    Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
    Definition: QuEST.c:1237
    std::vector< qcomp > QVector
    A complex vector, which can be zero-initialised with QVector(numAmps).
    Definition: utilities.hpp:60
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:310
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:1113
    #define qcomp
    TEST_CASE("calcDensityInnerProduct", "[calculations]")
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    -
    qreal getRealAmp(Qureg qureg, long long int index)
    Get the real component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:905
    +
    qreal getRealAmp(Qureg qureg, long long int index)
    Get the real component of the complex probability amplitude at an index in the state vector.
    Definition: QuEST.c:918
    Represents a diagonal complex operator on the full Hilbert state of a Qureg.
    Definition: QuEST.h:297
    @ PAULI_Y
    Definition: QuEST.h:96
    A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
    Definition: QuEST.h:277
    -
    int getNumQubits(Qureg qureg)
    Returns the number of qubits represented by qureg.
    Definition: QuEST.c:895
    -
    Complex calcInnerProduct(Qureg bra, Qureg ket)
    Computes the inner product of two equal-size state vectors, given by.
    Definition: QuEST.c:1137
    +
    int getNumQubits(Qureg qureg)
    Returns the number of qubits represented by qureg.
    Definition: QuEST.c:908
    +
    Complex calcInnerProduct(Qureg bra, Qureg ket)
    Computes the inner product of two equal-size state vectors, given by.
    Definition: QuEST.c:1150
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg, freeing its memory.
    Definition: QuEST.c:77
    QVector getRandomStateVector(int numQb)
    Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.
    Definition: utilities.cpp:468
    -
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1563
    +
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1578
    QMatrix getRandomQMatrix(int dim)
    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
    Definition: utilities.cpp:379
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    long long int getNumAmps(Qureg qureg)
    Returns the number of complex amplitudes in a state-vector qureg.
    Definition: QuEST.c:899
    +
    long long int getNumAmps(Qureg qureg)
    Returns the number of complex amplitudes in a state-vector qureg.
    Definition: QuEST.c:912
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:302
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    -
    qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
    Computes the expected value of a sum of products of Pauli operators.
    Definition: QuEST.c:1197
    +
    qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
    Computes the expected value of a sum of products of Pauli operators.
    Definition: QuEST.c:1210
    Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
    Definition: utilities.cpp:1488
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:327
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:308
    qreal real
    Definition: QuEST.h:105
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1399
    +
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1414
    qreal imag
    Definition: QuEST.h:106
    QMatrix getRandomDensityMatrix(int numQb)
    Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed sta...
    Definition: utilities.cpp:490
    Represents one complex number.
    Definition: QuEST.h:103
    QVector getRandomQVector(int dim)
    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
    Definition: utilities.cpp:435
    void initZeroState(Qureg qureg)
    Initialise qureg into the zero state.
    Definition: QuEST.c:113
    -
    qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
    Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
    Definition: QuEST.c:1145
    +
    qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
    Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
    Definition: QuEST.c:1158
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:398
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
    Definition: QuEST.c:50
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:728
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1383
    +
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1398
    void initPlusState(Qureg qureg)
    Initialise qureg into the plus state.
    Definition: QuEST.c:125
    -
    qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
    Computes the expected value of a product of Pauli operators.
    Definition: QuEST.c:1188
    +
    qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
    Computes the expected value of a product of Pauli operators.
    Definition: QuEST.c:1201
    -
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1503
    +
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1518
    diff --git a/docs/test__data__structures_8cpp.html b/docs/test__data__structures_8cpp.html index 613d6739e..233329188 100644 --- a/docs/test__data__structures_8cpp.html +++ b/docs/test__data__structures_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/test__data__structures_8cpp_source.html b/docs/test__data__structures_8cpp_source.html index c3730c93c..1fe4b75a7 100644 --- a/docs/test__data__structures_8cpp_source.html +++ b/docs/test__data__structures_8cpp_source.html @@ -27,7 +27,7 @@ @@ -1042,32 +1042,32 @@
    1074 }
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:39
    -
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1489
    +
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:45
    +
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1504
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    -
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    +
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    #define fromComplex(comp)
    @ PAULI_Z
    Definition: QuEST.h:96
    -
    int rank
    Definition: QuEST.h:363
    -
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1356
    +
    int rank
    Definition: QuEST.h:364
    +
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1369
    int numChunks
    The number of nodes between which the elements of this operator are split.
    Definition: QuEST.h:304
    @ PAULI_I
    Definition: QuEST.h:96
    TEST_CASE("fromComplex", "[data_structures]")
    -
    DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
    Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
    Definition: QuEST.c:1543
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    -
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1516
    -
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1509
    +
    DiagonalOp createDiagonalOpFromPauliHamilFile(char *fn, QuESTEnv env)
    Creates and initialiases a diagonal operator from the Z Pauli Hamiltonian encoded in file with filena...
    Definition: QuEST.c:1558
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    +
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1531
    +
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1524
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    void writeToFileSynch(char *fn, const string &contents)
    Writes contents to the file with filename fn, which is created and/or overwritten.
    Definition: utilities.cpp:1362
    int chunkId
    The position of the chunk of the operator held by this process in the full operator.
    Definition: QuEST.h:306
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:361
    -
    PauliHamil createPauliHamilFromFile(char *fn)
    Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
    Definition: QuEST.c:1405
    -
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
    Definition: QuEST.c:1528
    +
    Information about the environment the program is running in.
    Definition: QuEST.h:362
    +
    PauliHamil createPauliHamilFromFile(char *fn)
    Creates a PauliHamil instance, a real-weighted sum of products of Pauli operators,...
    Definition: QuEST.c:1420
    +
    void setDiagonalOpElems(DiagonalOp op, long long int startInd, qreal *real, qreal *imag, long long int numElems)
    Modifies a subset (starting at index startInd, and ending at index startInd + numElems) of the elemen...
    Definition: QuEST.c:1543
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    #define qreal
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    -
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    +
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    @ PAULI_X
    Definition: QuEST.h:96
    int numQubitsInStateVec
    Number of qubits in the state-vector - this is double the number represented for mixed states.
    Definition: QuEST.h:329
    void setUniqueFilename(char *outFn, char *prefix)
    Modifies outFn to be a filename of format prefix_NUM.txt where NUM is a new unique integer so far.
    Definition: utilities.cpp:1358
    @@ -1076,13 +1076,13 @@
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:310
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:1113
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:332
    -
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
    Definition: QuEST.c:1114
    +
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
    Definition: QuEST.c:1127
    qreal * termCoeffs
    The real coefficient of each Pauli product. This is an array of length PauliHamil....
    Definition: QuEST.h:283
    #define qcomp
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    +
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:42
    #define toComplex(scalar)
    -
    int numRanks
    Definition: QuEST.h:364
    +
    int numRanks
    Definition: QuEST.h:365
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:300
    int numSumTerms
    The number of terms in the weighted sum, or the number of Pauli products.
    Definition: QuEST.h:285
    Represents a diagonal complex operator on the full Hilbert state of a Qureg.
    Definition: QuEST.h:297
    @@ -1092,10 +1092,10 @@
    void setRandomDiagPauliHamil(PauliHamil hamil)
    Populates hamil with random coefficients and a random amount number of PAULI_I and PAULI_Z operators.
    Definition: utilities.cpp:1241
    qreal ** real
    Definition: QuEST.h:189
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
    Overwrites the entire DiagonalOp op with the given real and imag complex elements.
    Definition: QuEST.c:1522
    +
    void initDiagonalOp(DiagonalOp op, qreal *real, qreal *imag)
    Overwrites the entire DiagonalOp op with the given real and imag complex elements.
    Definition: QuEST.c:1537
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:341
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:302
    -
    void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
    Definition: QuEST.c:1535
    +
    void initDiagonalOpFromPauliHamil(DiagonalOp op, PauliHamil hamil)
    Populates the diagonal operator op to be equivalent to the given Pauli Hamiltonian hamil,...
    Definition: QuEST.c:1550
    int isDensityMatrix
    Whether this instance is a density-state representation.
    Definition: QuEST.h:325
    Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
    Create a new Qureg which is an exact clone of the passed qureg, which can be either a state-vector or...
    Definition: QuEST.c:64
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    @@ -1105,16 +1105,16 @@
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:308
    qreal real
    Definition: QuEST.h:105
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1399
    +
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1414
    qreal imag
    Definition: QuEST.h:106
    void deleteFilesWithPrefixSynch(char *prefix)
    Deletes all files with filename starting with prefix.
    Definition: utilities.cpp:1375
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:153
    Represents one complex number.
    Definition: QuEST.h:103
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:398
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
    Definition: QuEST.c:50
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1383
    +
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1398
    -
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1503
    +
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1518
    diff --git a/docs/test__decoherence_8cpp.html b/docs/test__decoherence_8cpp.html index 0b778b3fa..d182015ae 100644 --- a/docs/test__decoherence_8cpp.html +++ b/docs/test__decoherence_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/test__decoherence_8cpp_source.html b/docs/test__decoherence_8cpp_source.html index 324de665f..04b6c26e7 100644 --- a/docs/test__decoherence_8cpp_source.html +++ b/docs/test__decoherence_8cpp_source.html @@ -27,7 +27,7 @@ @@ -811,50 +811,50 @@
    793 }
    794 
    -
    void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit dephasing noise.
    Definition: QuEST.c:1237
    +
    void mixDephasing(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit dephasing noise.
    Definition: QuEST.c:1250
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    qreal real[4][4]
    Definition: QuEST.h:177
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    -
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1259
    -
    void mixDamping(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
    Definition: QuEST.c:1270
    -
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1356
    +
    void mixDepolarising(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1272
    +
    void mixDamping(Qureg qureg, int targetQubit, qreal prob)
    Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
    Definition: QuEST.c:1283
    +
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1369
    std::vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
    Returns a random Kraus map of #numOps 2^numQb-by-2^numQb operators, from an undisclosed distribution.
    Definition: utilities.cpp:578
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    -
    void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
    Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
    Definition: QuEST.c:1301
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    +
    void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
    Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
    Definition: QuEST.c:1314
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:421
    -
    void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1278
    +
    void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
    Definition: QuEST.c:1291
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:175
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    #define qreal
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    -
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    +
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
    Initialises cm with the values of qm.
    Definition: utilities.cpp:1033
    #define qcomp
    ComplexMatrix4 toComplexMatrix4(QMatrix qm)
    Returns a ComplexMatrix4 copy of QMatix qm.
    Definition: utilities.cpp:1027
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg, freeing its memory.
    Definition: QuEST.c:77
    -
    void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
    Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
    Definition: QuEST.c:1311
    +
    void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
    Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
    Definition: QuEST.c:1324
    qreal ** real
    Definition: QuEST.h:189
    -
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1563
    +
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1578
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit dephasing noise.
    Definition: QuEST.c:1247
    +
    void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
    Mixes a density matrix qureg to induce two-qubit dephasing noise.
    Definition: QuEST.c:1260
    qreal real[2][2]
    Definition: QuEST.h:139
    #define PREPARE_TEST(qureg, ref)
    Prepares a density matrix in the debug state, and the reference QMatrix.
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    ComplexMatrix2 toComplexMatrix2(QMatrix qm)
    Returns a ComplexMatrix2 copy of QMatix qm.
    Definition: utilities.cpp:1021
    Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
    Definition: utilities.cpp:1488
    int numQubitsRepresented
    The number of qubits represented in either the state-vector or density matrix.
    Definition: QuEST.h:327
    -
    void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
    Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
    Definition: QuEST.c:999
    +
    void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
    Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
    Definition: QuEST.c:1012
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
    Mixes a density matrix qureg to induce general single-qubit Pauli noise.
    Definition: QuEST.c:1290
    +
    void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
    Mixes a density matrix qureg to induce general single-qubit Pauli noise.
    Definition: QuEST.c:1303
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:153
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:398
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
    Definition: QuEST.c:50
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:728
    TEST_CASE("mixDamping", "[decoherence]")
    -
    void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
    Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
    Definition: QuEST.c:1321
    +
    void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
    Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
    Definition: QuEST.c:1334
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:137
    diff --git a/docs/test__gates_8cpp.html b/docs/test__gates_8cpp.html index 1284baabd..ccc2a2051 100644 --- a/docs/test__gates_8cpp.html +++ b/docs/test__gates_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/test__gates_8cpp_source.html b/docs/test__gates_8cpp_source.html index ee0708bc8..a0983ee53 100644 --- a/docs/test__gates_8cpp_source.html +++ b/docs/test__gates_8cpp_source.html @@ -27,7 +27,7 @@ @@ -349,12 +349,12 @@
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    -
    qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
    Definition: QuEST.c:953
    +
    qreal collapseToOutcome(Qureg qureg, int measureQubit, int outcome)
    Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
    Definition: QuEST.c:966
    -
    int measure(Qureg qureg, int measureQubit)
    Measures a single qubit, collapsing it randomly to 0 or 1.
    Definition: QuEST.c:985
    +
    int measure(Qureg qureg, int measureQubit)
    Measures a single qubit, collapsing it randomly to 0 or 1.
    Definition: QuEST.c:998
    #define qreal
    void toQureg(Qureg qureg, QVector vec)
    Initialises the state-vector qureg to have the same amplitudes as vec.
    Definition: utilities.cpp:1201
    -
    int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
    Definition: QuEST.c:972
    +
    int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
    Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
    Definition: QuEST.c:985
    std::vector< qcomp > QVector
    A complex vector, which can be zero-initialised with QVector(numAmps).
    Definition: utilities.hpp:60
    #define qcomp
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg, freeing its memory.
    Definition: QuEST.c:77
    diff --git a/docs/test__operators_8cpp.html b/docs/test__operators_8cpp.html index 94bd694db..56f30c15f 100644 --- a/docs/test__operators_8cpp.html +++ b/docs/test__operators_8cpp.html @@ -27,7 +27,7 @@ @@ -110,6 +110,8 @@    TEST_CASE ("applyPhaseFuncOverrides", "[operators]")   + TEST_CASE ("applyProjector", "[operators]") +   TEST_CASE ("applyQFT", "[operators]")    TEST_CASE ("applyTrotterCircuit", "[operators]") diff --git a/docs/test__operators_8cpp_source.html b/docs/test__operators_8cpp_source.html index 8e147f0ec..82365a767 100644 --- a/docs/test__operators_8cpp_source.html +++ b/docs/test__operators_8cpp_source.html @@ -27,7 +27,7 @@ @@ -1734,1881 +1734,2017 @@
    1723  qreal phase = 0;
    1724  for (int r=0; r<numRegs; r++)
    1725  phase += pow(regVals[i][r] - params[2+r], 2);
    -
    1726  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    1727  diagMatr[i][i] = expI(phase);
    -
    1728  }
    -
    1729 
    -
    1730  SECTION( "state-vector" ) {
    -
    1731 
    -
    1732  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1733  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1734  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1735  }
    -
    1736  SECTION( "density-matrix" ) {
    -
    1737 
    -
    1738  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1739  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1740  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1741  }
    -
    1742  }
    -
    1743  SECTION( "INVERSE_PRODUCT" ) {
    -
    1744 
    -
    1745  enum phaseFunc func = INVERSE_PRODUCT;
    -
    1746  qreal divPhase = getRandomReal(-4, 4);
    -
    1747 
    -
    1748  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1749  qreal phase = 1;
    -
    1750  for (int r=0; r<numRegs; r++)
    -
    1751  phase *= regVals[i][r];
    -
    1752  phase = (phase == 0.)? divPhase : 1. / phase;
    -
    1753  diagMatr[i][i] = expI(phase);
    -
    1754  }
    -
    1755 
    -
    1756  qreal params[] = {divPhase};
    -
    1757  int numParams = 1;
    -
    1758 
    -
    1759  SECTION( "state-vector" ) {
    -
    1760 
    -
    1761  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1762  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1763  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1764  }
    -
    1765  SECTION( "density-matrix" ) {
    -
    1766 
    -
    1767  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1768  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1769  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1770  }
    -
    1771  }
    -
    1772  SECTION( "SCALED_PRODUCT" ) {
    -
    1773 
    -
    1774  enum phaseFunc func = SCALED_PRODUCT;
    -
    1775  qreal coeff = getRandomReal(-10, 10);
    -
    1776 
    -
    1777  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1778  qreal phase = 1;
    -
    1779  for (int r=0; r<numRegs; r++)
    -
    1780  phase *= regVals[i][r];
    -
    1781  diagMatr[i][i] = expI(coeff * phase);
    -
    1782  }
    -
    1783 
    -
    1784  qreal params[] = {coeff};
    -
    1785  int numParams = 1;
    -
    1786 
    -
    1787  SECTION( "state-vector" ) {
    -
    1788 
    -
    1789  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1790  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1791  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1792  }
    -
    1793  SECTION( "density-matrix" ) {
    -
    1794 
    -
    1795  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1796  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1797  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1798  }
    -
    1799  }
    -
    1800  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    -
    1801 
    -
    1802  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    -
    1803  qreal coeff = getRandomReal(-10, 10);
    -
    1804  qreal divPhase = getRandomReal(-4, 4);
    -
    1805  qreal params[] = {coeff, divPhase};
    -
    1806  int numParams = 2;
    -
    1807 
    -
    1808  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1809  qreal phase = 1;
    -
    1810  for (int r=0; r<numRegs; r++)
    -
    1811  phase *= regVals[i][r];
    -
    1812  phase = (phase == 0)? divPhase : coeff / phase;
    -
    1813  diagMatr[i][i] = expI(phase);
    -
    1814  }
    -
    1815 
    -
    1816  SECTION( "state-vector" ) {
    -
    1817 
    -
    1818  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1819  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1820  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1821  }
    -
    1822  SECTION( "density-matrix" ) {
    -
    1823 
    -
    1824  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1825  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1826  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1827  }
    -
    1828  }
    -
    1829  SECTION( "INVERSE_DISTANCE" ) {
    -
    1830 
    -
    1831  enum phaseFunc func = INVERSE_DISTANCE;
    -
    1832  qreal divPhase = getRandomReal( -4, 4 );
    -
    1833  qreal params[] = {divPhase};
    -
    1834  int numParams = 1;
    -
    1835 
    -
    1836  // test only if there are an even number of registers
    -
    1837  if (numRegs%2 == 0) {
    -
    1838 
    -
    1839  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1840  qreal phase = 0;
    -
    1841  for (int r=0; r<numRegs; r+=2)
    -
    1842  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    1843  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    -
    1844  diagMatr[i][i] = expI(phase);
    -
    1845  }
    -
    1846  }
    -
    1847 
    -
    1848  SECTION( "state-vector" ) {
    -
    1849 
    -
    1850  if (numRegs%2 == 0) {
    -
    1851  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1852  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1853  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1854  }
    -
    1855  }
    -
    1856  SECTION( "density-matrix" ) {
    -
    1857 
    -
    1858  if (numRegs%2 == 0) {
    -
    1859  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1860  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1861  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1862  }
    -
    1863  }
    -
    1864  }
    -
    1865  SECTION( "SCALED_DISTANCE" ) {
    -
    1866 
    -
    1867  enum phaseFunc func = SCALED_DISTANCE;
    -
    1868  qreal coeff = getRandomReal( -10, 10 );
    -
    1869  qreal params[] = {coeff};
    -
    1870  int numParams = 1;
    -
    1871 
    -
    1872  // test only if there are an even number of registers
    -
    1873  if (numRegs%2 == 0) {
    -
    1874 
    -
    1875  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1876  qreal phase = 0;
    -
    1877  for (int r=0; r<numRegs; r+=2)
    -
    1878  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    1879  phase = coeff * sqrt(phase);
    -
    1880  diagMatr[i][i] = expI(phase);
    -
    1881  }
    -
    1882  }
    -
    1883 
    -
    1884  SECTION( "state-vector" ) {
    -
    1885 
    -
    1886  if (numRegs%2 == 0) {
    -
    1887  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1888  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1889  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1890  }
    -
    1891  }
    -
    1892  SECTION( "density-matrix" ) {
    -
    1893 
    -
    1894  if (numRegs%2 == 0) {
    -
    1895  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1896  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1897  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1898  }
    -
    1899  }
    -
    1900  }
    -
    1901  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    -
    1902 
    -
    1903  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    -
    1904  qreal coeff = getRandomReal( -10, 10 );
    -
    1905  qreal divPhase = getRandomReal( -4, 4 );
    -
    1906  qreal params[] = {coeff, divPhase};
    -
    1907  int numParams = 2;
    -
    1908 
    -
    1909  // test only if there are an even number of registers
    -
    1910  if (numRegs%2 == 0) {
    -
    1911 
    -
    1912  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1913  qreal phase = 0;
    -
    1914  for (int r=0; r<numRegs; r+=2)
    -
    1915  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    1916  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    -
    1917  diagMatr[i][i] = expI(phase);
    -
    1918  }
    -
    1919  }
    -
    1920 
    -
    1921  SECTION( "state-vector" ) {
    -
    1922 
    -
    1923  if (numRegs%2 == 0) {
    -
    1924  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1925  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1926  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1927  }
    -
    1928  }
    -
    1929  SECTION( "density-matrix" ) {
    -
    1930 
    -
    1931  if (numRegs%2 == 0) {
    -
    1932  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1933  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1934  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1935  }
    -
    1936  }
    -
    1937  }
    -
    1938  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    -
    1939 
    - -
    1941  int numParams = 2 + numRegs/2;
    -
    1942  qreal params[numParams];
    -
    1943 
    -
    1944  // test only if there are an even number of registers
    -
    1945  if (numRegs%2 == 0) {
    -
    1946 
    -
    1947  params[0] = getRandomReal( -10, 10 ); // scaling
    -
    1948  params[1] = getRandomReal( -4, 4 ); // divergence override
    -
    1949  for (int r=0; r<numRegs/2; r++)
    -
    1950  params[2+r] = getRandomReal( -8, 8 ); // shifts
    -
    1951 
    -
    1952  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    1953  qreal phase = 0;
    -
    1954  for (int r=0; r<numRegs; r+=2)
    -
    1955  phase += pow(regVals[i][r+1]-regVals[i][r]-params[2+r/2], 2);
    -
    1956  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    1957  diagMatr[i][i] = expI(phase);
    -
    1958  }
    -
    1959  }
    -
    1960 
    -
    1961  SECTION( "state-vector" ) {
    -
    1962 
    -
    1963  if (numRegs%2 == 0) {
    -
    1964  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1965  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    1966  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    1967  }
    -
    1968  }
    -
    1969  SECTION( "density-matrix" ) {
    -
    1970 
    -
    1971  if (numRegs%2 == 0) {
    -
    1972  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    -
    1973  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    1974  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    1975  }
    -
    1976  }
    -
    1977  }
    -
    1978  }
    -
    1979  SECTION( "input validation" ) {
    -
    1980 
    -
    1981  int numRegs = 2;
    -
    1982  int numQubitsPerReg[] = {2,3};
    -
    1983  int regs[] = {0,1,2,3,4};
    -
    1984 
    -
    1985  SECTION( "number of registers" ) {
    -
    1986 
    -
    1987  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    -
    1988  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubit subregisters") );
    -
    1989  }
    -
    1990  SECTION( "number of qubits" ) {
    -
    1991 
    -
    1992  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    -
    1993  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubits") );
    -
    1994  }
    -
    1995  SECTION( "repetition of qubits" ) {
    -
    1996 
    -
    1997  regs[GENERATE(2,3,4)] = regs[1];
    -
    1998  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("The qubits must be unique") );
    -
    1999  }
    -
    2000  SECTION( "qubit indices" ) {
    -
    2001 
    -
    2002  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    -
    2003  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid qubit index") );
    -
    2004  }
    -
    2005  SECTION( "bit encoding name" ) {
    -
    2006 
    -
    2007  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    -
    2008  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0), Contains("Invalid bit encoding") );
    -
    2009  }
    -
    2010  SECTION( "two's complement register" ) {
    -
    2011 
    -
    2012  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    -
    2013  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    -
    2014  }
    -
    2015  SECTION( "phase function name" ) {
    -
    2016 
    -
    2017  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    -
    2018  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0), Contains("Invalid named phase function") );
    -
    2019  }
    -
    2020  SECTION( "phase function parameters" ) {
    -
    2021 
    -
    2022  qreal params[numRegs + 3];
    -
    2023  for (int r=0; r<numRegs + 3; r++)
    -
    2024  params[r] = 0;
    -
    2025 
    -
    2026  SECTION( "no parameter functions" ) {
    -
    2027 
    -
    2028  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    -
    2029  int numParams = GENERATE( -1, 1, 2 );
    -
    2030  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2031  }
    -
    2032  SECTION( "single parameter functions" ) {
    -
    2033 
    - -
    2035  int numParams = GENERATE( -1, 0, 2 );
    -
    2036  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2037  }
    -
    2038  SECTION( "two parameter functions" ) {
    -
    2039 
    - -
    2041  int numParams = GENERATE( 0, 1, 3 );
    -
    2042  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2043  }
    -
    2044  SECTION( "shifted distance" ) {
    -
    2045 
    -
    2046  if (numRegs%2 == 0) {
    - -
    2048  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    -
    2049  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2050  }
    -
    2051  }
    -
    2052  SECTION( "shifted norm" ) {
    -
    2053 
    - -
    2055  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    -
    2056  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    -
    2057  }
    -
    2058  }
    -
    2059  SECTION( "distance pair registers" ) {
    -
    2060 
    -
    2061  int numQb[] = {1,1,1,1,1};
    -
    2062  int qb[] = {0,1,2,3,4};
    -
    2063 
    -
    2064  numRegs = GENERATE( 1, 3, 5 );
    -
    2065  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    -
    2066  }
    -
    2067  }
    -
    2068  CLEANUP_TEST( quregVec, quregMatr );
    -
    2069 }
    -
    2070 
    -
    2071 
    +
    1726  phase = sqrt(phase);
    +
    1727  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    1728  diagMatr[i][i] = expI(phase);
    +
    1729  }
    +
    1730 
    +
    1731  SECTION( "state-vector" ) {
    +
    1732 
    +
    1733  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1734  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1735  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1736  }
    +
    1737  SECTION( "density-matrix" ) {
    +
    1738 
    +
    1739  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1740  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1741  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1742  }
    +
    1743  }
    +
    1744  SECTION( "INVERSE_PRODUCT" ) {
    +
    1745 
    +
    1746  enum phaseFunc func = INVERSE_PRODUCT;
    +
    1747  qreal divPhase = getRandomReal(-4, 4);
    +
    1748 
    +
    1749  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1750  qreal phase = 1;
    +
    1751  for (int r=0; r<numRegs; r++)
    +
    1752  phase *= regVals[i][r];
    +
    1753  phase = (phase == 0.)? divPhase : 1. / phase;
    +
    1754  diagMatr[i][i] = expI(phase);
    +
    1755  }
    +
    1756 
    +
    1757  qreal params[] = {divPhase};
    +
    1758  int numParams = 1;
    +
    1759 
    +
    1760  SECTION( "state-vector" ) {
    +
    1761 
    +
    1762  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1763  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1764  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1765  }
    +
    1766  SECTION( "density-matrix" ) {
    +
    1767 
    +
    1768  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1769  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1770  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1771  }
    +
    1772  }
    +
    1773  SECTION( "SCALED_PRODUCT" ) {
    +
    1774 
    +
    1775  enum phaseFunc func = SCALED_PRODUCT;
    +
    1776  qreal coeff = getRandomReal(-10, 10);
    +
    1777 
    +
    1778  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1779  qreal phase = 1;
    +
    1780  for (int r=0; r<numRegs; r++)
    +
    1781  phase *= regVals[i][r];
    +
    1782  diagMatr[i][i] = expI(coeff * phase);
    +
    1783  }
    +
    1784 
    +
    1785  qreal params[] = {coeff};
    +
    1786  int numParams = 1;
    +
    1787 
    +
    1788  SECTION( "state-vector" ) {
    +
    1789 
    +
    1790  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1791  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1792  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1793  }
    +
    1794  SECTION( "density-matrix" ) {
    +
    1795 
    +
    1796  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1797  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1798  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1799  }
    +
    1800  }
    +
    1801  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    +
    1802 
    +
    1803  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    +
    1804  qreal coeff = getRandomReal(-10, 10);
    +
    1805  qreal divPhase = getRandomReal(-4, 4);
    +
    1806  qreal params[] = {coeff, divPhase};
    +
    1807  int numParams = 2;
    +
    1808 
    +
    1809  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1810  qreal phase = 1;
    +
    1811  for (int r=0; r<numRegs; r++)
    +
    1812  phase *= regVals[i][r];
    +
    1813  phase = (phase == 0)? divPhase : coeff / phase;
    +
    1814  diagMatr[i][i] = expI(phase);
    +
    1815  }
    +
    1816 
    +
    1817  SECTION( "state-vector" ) {
    +
    1818 
    +
    1819  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1820  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1821  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1822  }
    +
    1823  SECTION( "density-matrix" ) {
    +
    1824 
    +
    1825  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1826  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1827  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1828  }
    +
    1829  }
    +
    1830  SECTION( "INVERSE_DISTANCE" ) {
    +
    1831 
    +
    1832  enum phaseFunc func = INVERSE_DISTANCE;
    +
    1833  qreal divPhase = getRandomReal( -4, 4 );
    +
    1834  qreal params[] = {divPhase};
    +
    1835  int numParams = 1;
    +
    1836 
    +
    1837  // test only if there are an even number of registers
    +
    1838  if (numRegs%2 == 0) {
    +
    1839 
    +
    1840  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1841  qreal phase = 0;
    +
    1842  for (int r=0; r<numRegs; r+=2)
    +
    1843  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    1844  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    +
    1845  diagMatr[i][i] = expI(phase);
    +
    1846  }
    +
    1847  }
    +
    1848 
    +
    1849  SECTION( "state-vector" ) {
    +
    1850 
    +
    1851  if (numRegs%2 == 0) {
    +
    1852  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1853  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1854  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1855  }
    +
    1856  }
    +
    1857  SECTION( "density-matrix" ) {
    +
    1858 
    +
    1859  if (numRegs%2 == 0) {
    +
    1860  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1861  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1862  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1863  }
    +
    1864  }
    +
    1865  }
    +
    1866  SECTION( "SCALED_DISTANCE" ) {
    +
    1867 
    +
    1868  enum phaseFunc func = SCALED_DISTANCE;
    +
    1869  qreal coeff = getRandomReal( -10, 10 );
    +
    1870  qreal params[] = {coeff};
    +
    1871  int numParams = 1;
    +
    1872 
    +
    1873  // test only if there are an even number of registers
    +
    1874  if (numRegs%2 == 0) {
    +
    1875 
    +
    1876  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1877  qreal phase = 0;
    +
    1878  for (int r=0; r<numRegs; r+=2)
    +
    1879  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    1880  phase = coeff * sqrt(phase);
    +
    1881  diagMatr[i][i] = expI(phase);
    +
    1882  }
    +
    1883  }
    +
    1884 
    +
    1885  SECTION( "state-vector" ) {
    +
    1886 
    +
    1887  if (numRegs%2 == 0) {
    +
    1888  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1889  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1890  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1891  }
    +
    1892  }
    +
    1893  SECTION( "density-matrix" ) {
    +
    1894 
    +
    1895  if (numRegs%2 == 0) {
    +
    1896  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1897  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1898  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1899  }
    +
    1900  }
    +
    1901  }
    +
    1902  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    +
    1903 
    +
    1904  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    +
    1905  qreal coeff = getRandomReal( -10, 10 );
    +
    1906  qreal divPhase = getRandomReal( -4, 4 );
    +
    1907  qreal params[] = {coeff, divPhase};
    +
    1908  int numParams = 2;
    +
    1909 
    +
    1910  // test only if there are an even number of registers
    +
    1911  if (numRegs%2 == 0) {
    +
    1912 
    +
    1913  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1914  qreal phase = 0;
    +
    1915  for (int r=0; r<numRegs; r+=2)
    +
    1916  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    1917  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    +
    1918  diagMatr[i][i] = expI(phase);
    +
    1919  }
    +
    1920  }
    +
    1921 
    +
    1922  SECTION( "state-vector" ) {
    +
    1923 
    +
    1924  if (numRegs%2 == 0) {
    +
    1925  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1926  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1927  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1928  }
    +
    1929  }
    +
    1930  SECTION( "density-matrix" ) {
    +
    1931 
    +
    1932  if (numRegs%2 == 0) {
    +
    1933  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1934  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1935  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1936  }
    +
    1937  }
    +
    1938  }
    +
    1939  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    +
    1940 
    + +
    1942  int numParams = 2 + numRegs/2;
    +
    1943  qreal params[numParams];
    +
    1944 
    +
    1945  // test only if there are an even number of registers
    +
    1946  if (numRegs%2 == 0) {
    +
    1947 
    +
    1948  params[0] = getRandomReal( -10, 10 ); // scaling
    +
    1949  params[1] = getRandomReal( -4, 4 ); // divergence override
    +
    1950  for (int r=0; r<numRegs/2; r++)
    +
    1951  params[2+r] = getRandomReal( -8, 8 ); // shifts
    +
    1952 
    +
    1953  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    1954  qreal phase = 0;
    +
    1955  for (int r=0; r<numRegs; r+=2)
    +
    1956  phase += pow(regVals[i][r]-regVals[i][r+1]-params[2+r/2], 2);
    +
    1957  phase = sqrt(phase);
    +
    1958  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    1959  diagMatr[i][i] = expI(phase);
    +
    1960  }
    +
    1961  }
    +
    1962 
    +
    1963  SECTION( "state-vector" ) {
    +
    1964 
    +
    1965  if (numRegs%2 == 0) {
    +
    1966  applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1967  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    1968  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    1969  }
    +
    1970  }
    +
    1971  SECTION( "density-matrix" ) {
    +
    1972 
    +
    1973  if (numRegs%2 == 0) {
    +
    1974  applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
    +
    1975  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    1976  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    1977  }
    +
    1978  }
    +
    1979  }
    +
    1980  }
    +
    1981  SECTION( "input validation" ) {
    +
    1982 
    +
    1983  int numRegs = 2;
    +
    1984  int numQubitsPerReg[] = {2,3};
    +
    1985  int regs[] = {0,1,2,3,4};
    +
    1986 
    +
    1987  SECTION( "number of registers" ) {
    +
    1988 
    +
    1989  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    +
    1990  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubit subregisters") );
    +
    1991  }
    +
    1992  SECTION( "number of qubits" ) {
    +
    1993 
    +
    1994  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    +
    1995  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid number of qubits") );
    +
    1996  }
    +
    1997  SECTION( "repetition of qubits" ) {
    +
    1998 
    +
    1999  regs[GENERATE(2,3,4)] = regs[1];
    +
    2000  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("The qubits must be unique") );
    +
    2001  }
    +
    2002  SECTION( "qubit indices" ) {
    +
    2003 
    +
    2004  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    +
    2005  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), Contains("Invalid qubit index") );
    +
    2006  }
    +
    2007  SECTION( "bit encoding name" ) {
    +
    2008 
    +
    2009  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    +
    2010  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0), Contains("Invalid bit encoding") );
    +
    2011  }
    +
    2012  SECTION( "two's complement register" ) {
    +
    2013 
    +
    2014  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    +
    2015  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    +
    2016  }
    +
    2017  SECTION( "phase function name" ) {
    +
    2018 
    +
    2019  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    +
    2020  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0), Contains("Invalid named phase function") );
    +
    2021  }
    +
    2022  SECTION( "phase function parameters" ) {
    +
    2023 
    +
    2024  qreal params[numRegs + 3];
    +
    2025  for (int r=0; r<numRegs + 3; r++)
    +
    2026  params[r] = 0;
    +
    2027 
    +
    2028  SECTION( "no parameter functions" ) {
    +
    2029 
    +
    2030  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    +
    2031  int numParams = GENERATE( -1, 1, 2 );
    +
    2032  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2033  }
    +
    2034  SECTION( "single parameter functions" ) {
    +
    2035 
    + +
    2037  int numParams = GENERATE( -1, 0, 2 );
    +
    2038  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2039  }
    +
    2040  SECTION( "two parameter functions" ) {
    +
    2041 
    + +
    2043  int numParams = GENERATE( 0, 1, 3 );
    +
    2044  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2045  }
    +
    2046  SECTION( "shifted distance" ) {
    +
    2047 
    +
    2048  if (numRegs%2 == 0) {
    + +
    2050  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    +
    2051  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2052  }
    +
    2053  }
    +
    2054  SECTION( "shifted norm" ) {
    +
    2055 
    + +
    2057  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    +
    2058  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), Contains("Invalid number of parameters") );
    +
    2059  }
    +
    2060  }
    +
    2061  SECTION( "distance pair registers" ) {
    +
    2062 
    +
    2063  int numQb[] = {1,1,1,1,1};
    +
    2064  int qb[] = {0,1,2,3,4};
    +
    2065 
    +
    2066  numRegs = GENERATE( 1, 3, 5 );
    +
    2067  REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    +
    2068  }
    +
    2069  }
    +
    2070  CLEANUP_TEST( quregVec, quregMatr );
    +
    2071 }
    2072 
    -
    2077 TEST_CASE( "applyParamNamedPhaseFuncOverrides", "[operators]" ) {
    -
    2078 
    -
    2079  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2080 
    -
    2081  SECTION( "correctness" ) {
    -
    2082 
    -
    2083  // try every kind of binary encoding
    -
    2084  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    -
    2085 
    -
    2086  // try every possible number of registers
    -
    2087  // (between #qubits containing 1, and 1 containing #qubits)
    -
    2088  int numRegs;
    -
    2089  int maxNumRegs = 0;
    -
    2090  if (encoding == UNSIGNED)
    -
    2091  maxNumRegs = NUM_QUBITS;
    -
    2092  if (encoding == TWOS_COMPLEMENT)
    -
    2093  maxNumRegs = NUM_QUBITS/2; // floors
    -
    2094  numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
    -
    2095 
    -
    2096  // try every possible total number of involved qubits
    -
    2097  int totalNumQubits;
    -
    2098  int minTotalQubits = 0;
    -
    2099  if (encoding == UNSIGNED)
    -
    2100  // each register must contain at least 1 qubit
    -
    2101  minTotalQubits = numRegs;
    -
    2102  if (encoding == TWOS_COMPLEMENT)
    -
    2103  // each register must contain at least 2 qubits
    -
    2104  minTotalQubits = 2*numRegs;
    -
    2105  totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
    -
    2106 
    -
    2107  // try every qubits subset and ordering
    -
    2108  int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
    -
    2109 
    -
    2110  // assign each sub-reg its minimum length
    -
    2111  int unallocQubits = totalNumQubits;
    -
    2112  int numQubitsPerReg[numRegs];
    -
    2113  for (int i=0; i<numRegs; i++)
    -
    2114  if (encoding == UNSIGNED) {
    -
    2115  numQubitsPerReg[i] = 1;
    -
    2116  unallocQubits -= 1;
    -
    2117  }
    -
    2118  else if (encoding == TWOS_COMPLEMENT) {
    -
    2119  numQubitsPerReg[i] = 2;
    -
    2120  unallocQubits -= 2;
    -
    2121  }
    -
    2122  // and randomly allocate the remaining qubits between the registers
    -
    2123  while (unallocQubits > 0) {
    -
    2124  numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
    -
    2125  unallocQubits--;
    -
    2126  }
    -
    2127 
    -
    2128 
    -
    2129  // choose a random number of overrides (even overriding every amplitude)
    -
    2130  int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
    -
    2131 
    -
    2132  // randomise each override index (uniqueness isn't checked)
    -
    2133  long long int overrideInds[numOverrides*numRegs];
    -
    2134  int flatInd = 0;
    -
    2135  for (int v=0; v<numOverrides; v++) {
    -
    2136  for (int r=0; r<numRegs; r++) {
    -
    2137  if (encoding == UNSIGNED)
    -
    2138  overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
    -
    2139  else if (encoding == TWOS_COMPLEMENT)
    -
    2140  overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
    -
    2141  flatInd++;
    -
    2142  }
    -
    2143  }
    -
    2144 
    -
    2145  // override to a random phase
    -
    2146  qreal overridePhases[numOverrides];
    -
    2147  for (int v=0; v<numOverrides; v++)
    -
    2148  overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    -
    2149 
    -
    2150 
    -
    2151  // determine the values corresponding to each register for all basis states
    -
    2152  qreal regVals[1<<totalNumQubits][numRegs];
    -
    2153  for (long long int i=0; i<(1<<totalNumQubits); i++) {
    -
    2154 
    -
    2155  long long int bits = i;
    -
    2156  for (int r=0; r<numRegs; r++) {
    -
    2157  regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
    -
    2158  bits = bits >> numQubitsPerReg[r];
    -
    2159 
    -
    2160  if (encoding == TWOS_COMPLEMENT)
    -
    2161  regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
    -
    2162  }
    -
    2163  }
    -
    2164 
    -
    2165  /* produce a reference diagonal matrix which assumes the qubits are
    -
    2166  * contiguous and strictly increasing between the registers, and hence
    -
    2167  * only depends on the number of qubits in each register.
    -
    2168  */
    -
    2169  QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
    -
    2170 
    -
    2171 
    -
    2172  SECTION( "INVERSE_NORM" ) {
    -
    2173 
    -
    2174  enum phaseFunc func = INVERSE_NORM;
    -
    2175  qreal divPhase = getRandomReal(-4, 4);
    -
    2176  qreal params[] = {divPhase};
    -
    2177  int numParams = 1;
    -
    2178 
    -
    2179  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2180  qreal phase = 0;
    -
    2181  for (int r=0; r<numRegs; r++)
    -
    2182  phase += pow(regVals[i][r], 2);
    -
    2183  phase = (phase == 0.)? divPhase : 1/sqrt(phase);
    -
    2184  diagMatr[i][i] = expI(phase);
    -
    2185  }
    -
    2186  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2187 
    -
    2188  SECTION( "state-vector" ) {
    -
    2189 
    -
    2190  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2191  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2192  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2193  }
    -
    2194  SECTION( "density-matrix" ) {
    -
    2195 
    -
    2196  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2197  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2198  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2199  }
    -
    2200  }
    -
    2201  SECTION( "SCALED_NORM" ) {
    -
    2202 
    -
    2203  enum phaseFunc func = SCALED_NORM;
    -
    2204  qreal coeff = getRandomReal(-10, 10);
    -
    2205  qreal params[] = {coeff};
    -
    2206  int numParams = 1;
    -
    2207 
    -
    2208  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2209  qreal phase = 0;
    -
    2210  for (int r=0; r<numRegs; r++)
    -
    2211  phase += pow(regVals[i][r], 2);
    -
    2212  phase = coeff * sqrt(phase);
    -
    2213  diagMatr[i][i] = expI(phase);
    -
    2214  }
    -
    2215  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2216 
    -
    2217  SECTION( "state-vector" ) {
    -
    2218 
    -
    2219  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2220  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2221  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2222  }
    -
    2223  SECTION( "density-matrix" ) {
    -
    2224 
    -
    2225  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2226  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2227  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2228  }
    -
    2229  }
    -
    2230  SECTION( "SCALED_INVERSE_NORM" ) {
    -
    2231 
    -
    2232  enum phaseFunc func = SCALED_INVERSE_NORM;
    -
    2233  qreal coeff = getRandomReal(-10, 10);
    -
    2234  qreal divPhase = getRandomReal(-4, 4);
    -
    2235  qreal params[] = {coeff, divPhase};
    -
    2236  int numParams = 2;
    -
    2237 
    -
    2238  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2239  qreal phase = 0;
    -
    2240  for (int r=0; r<numRegs; r++)
    -
    2241  phase += pow(regVals[i][r], 2);
    -
    2242  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    -
    2243  diagMatr[i][i] = expI(phase);
    -
    2244  }
    -
    2245  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2246 
    -
    2247  SECTION( "state-vector" ) {
    -
    2248 
    -
    2249  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2250  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2251  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2252  }
    -
    2253  SECTION( "density-matrix" ) {
    -
    2254 
    -
    2255  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2256  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2257  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2258  }
    -
    2259  }
    -
    2260  SECTION( "SCALED_INVERSE_SHIFTED_NORM" ) {
    -
    2261 
    - -
    2263  int numParams = 2 + numRegs;
    -
    2264  qreal params[numParams];
    -
    2265  params[0] = getRandomReal(-10, 10); // scaling
    -
    2266  params[1] = getRandomReal(-4, 4); // divergence override
    -
    2267  for (int r=0; r<numRegs; r++)
    -
    2268  params[2+r] = getRandomReal(-8, 8); // shifts
    -
    2269 
    -
    2270  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2271  qreal phase = 0;
    -
    2272  for (int r=0; r<numRegs; r++)
    -
    2273  phase += pow(regVals[i][r] - params[2+r], 2);
    -
    2274  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    2275  diagMatr[i][i] = expI(phase);
    -
    2276  }
    -
    2277  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2278 
    -
    2279  SECTION( "state-vector" ) {
    -
    2280 
    -
    2281  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2282  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2283  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2284  }
    -
    2285  SECTION( "density-matrix" ) {
    -
    2286 
    -
    2287  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2288  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2289  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2290  }
    -
    2291  }
    -
    2292  SECTION( "INVERSE_PRODUCT" ) {
    -
    2293 
    -
    2294  enum phaseFunc func = INVERSE_PRODUCT;
    -
    2295  qreal divPhase = getRandomReal(-4, 4);
    -
    2296  qreal params[] = {divPhase};
    -
    2297  int numParams = 1;
    -
    2298 
    -
    2299  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2300  qreal phase = 1;
    -
    2301  for (int r=0; r<numRegs; r++)
    -
    2302  phase *= regVals[i][r];
    -
    2303  phase = (phase == 0.)? divPhase : 1. / phase;
    -
    2304  diagMatr[i][i] = expI(phase);
    -
    2305  }
    -
    2306  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2307 
    -
    2308  SECTION( "state-vector" ) {
    -
    2309 
    -
    2310  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2311  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2312  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2313  }
    -
    2314  SECTION( "density-matrix" ) {
    -
    2315 
    -
    2316  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2317  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2318  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2319  }
    -
    2320  }
    -
    2321  SECTION( "SCALED_PRODUCT" ) {
    -
    2322 
    -
    2323  enum phaseFunc func = SCALED_PRODUCT;
    -
    2324  qreal coeff = getRandomReal(-10, 10);
    -
    2325  qreal params[] = {coeff};
    -
    2326  int numParams = 1;
    -
    2327 
    -
    2328  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2329  qreal phase = 1;
    -
    2330  for (int r=0; r<numRegs; r++)
    -
    2331  phase *= regVals[i][r];
    -
    2332  diagMatr[i][i] = expI(coeff * phase);
    -
    2333  }
    -
    2334  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2335 
    -
    2336  SECTION( "state-vector" ) {
    -
    2337 
    -
    2338  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2339  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2340  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2341  }
    -
    2342  SECTION( "density-matrix" ) {
    -
    2343 
    -
    2344  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2345  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2346  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2347  }
    -
    2348  }
    -
    2349  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    -
    2350 
    -
    2351  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    -
    2352  qreal coeff = getRandomReal(-10, 10);
    -
    2353  qreal divPhase = getRandomReal(-4, 4);
    -
    2354  qreal params[] = {coeff, divPhase};
    -
    2355  int numParams = 2;
    -
    2356 
    -
    2357  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2358  qreal phase = 1;
    -
    2359  for (int r=0; r<numRegs; r++)
    -
    2360  phase *= regVals[i][r];
    -
    2361  phase = (phase == 0)? divPhase : coeff / phase;
    -
    2362  diagMatr[i][i] = expI(phase);
    -
    2363  }
    -
    2364  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2365 
    -
    2366  SECTION( "state-vector" ) {
    -
    2367 
    -
    2368  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2369  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2370  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2371  }
    -
    2372  SECTION( "density-matrix" ) {
    -
    2373 
    -
    2374  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2375  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2376  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2377  }
    -
    2378  }
    -
    2379  SECTION( "INVERSE_DISTANCE" ) {
    -
    2380 
    -
    2381  enum phaseFunc func = INVERSE_DISTANCE;
    -
    2382  qreal divPhase = getRandomReal( -4, 4 );
    -
    2383  qreal params[] = {divPhase};
    -
    2384  int numParams = 1;
    -
    2385 
    -
    2386  // test only if there are an even number of registers
    -
    2387  if (numRegs%2 == 0) {
    -
    2388 
    -
    2389  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2390  qreal phase = 0;
    -
    2391  for (int r=0; r<numRegs; r+=2)
    -
    2392  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    2393  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    -
    2394  diagMatr[i][i] = expI(phase);
    -
    2395  }
    -
    2396  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2397  }
    -
    2398 
    -
    2399  SECTION( "state-vector" ) {
    -
    2400 
    -
    2401  if (numRegs%2 == 0) {
    -
    2402  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2403  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2404  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2405  }
    -
    2406  }
    -
    2407  SECTION( "density-matrix" ) {
    -
    2408 
    -
    2409  if (numRegs%2 == 0) {
    -
    2410  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2411  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2412  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2413  }
    -
    2414  }
    -
    2415  }
    -
    2416  SECTION( "SCALED_DISTANCE" ) {
    -
    2417 
    -
    2418  enum phaseFunc func = SCALED_DISTANCE;
    -
    2419  qreal coeff = getRandomReal( -10, 10 );
    -
    2420  qreal params[] = {coeff};
    -
    2421  int numParams = 1;
    -
    2422 
    -
    2423  // test only if there are an even number of registers
    -
    2424  if (numRegs%2 == 0) {
    -
    2425 
    -
    2426  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2427  qreal phase = 0;
    -
    2428  for (int r=0; r<numRegs; r+=2)
    -
    2429  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    2430  phase = coeff * sqrt(phase);
    -
    2431  diagMatr[i][i] = expI(phase);
    -
    2432  }
    -
    2433  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2434  }
    -
    2435 
    -
    2436  SECTION( "state-vector" ) {
    -
    2437 
    -
    2438  if (numRegs%2 == 0) {
    -
    2439  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2440  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2441  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2442  }
    -
    2443  }
    -
    2444  SECTION( "density-matrix" ) {
    -
    2445 
    -
    2446  if (numRegs%2 == 0) {
    -
    2447  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2448  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2449  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2450  }
    -
    2451  }
    -
    2452  }
    -
    2453  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    -
    2454 
    -
    2455  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    -
    2456  qreal coeff = getRandomReal( -10, 10 );
    -
    2457  qreal divPhase = getRandomReal( -4, 4 );
    -
    2458  qreal params[] = {coeff, divPhase};
    -
    2459  int numParams = 2;
    -
    2460 
    -
    2461  // test only if there are an even number of registers
    -
    2462  if (numRegs%2 == 0) {
    -
    2463 
    -
    2464  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2465  qreal phase = 0;
    -
    2466  for (int r=0; r<numRegs; r+=2)
    -
    2467  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    -
    2468  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    -
    2469  diagMatr[i][i] = expI(phase);
    -
    2470  }
    -
    2471  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2472  }
    -
    2473 
    -
    2474  SECTION( "state-vector" ) {
    -
    2475 
    -
    2476  if (numRegs%2 == 0) {
    -
    2477  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2478  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2479  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2480  }
    -
    2481  }
    -
    2482  SECTION( "density-matrix" ) {
    -
    2483 
    -
    2484  if (numRegs%2 == 0) {
    -
    2485  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2486  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2487  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2488  }
    -
    2489  }
    -
    2490  }
    -
    2491  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    -
    2492 
    - -
    2494  int numParams = 2 + numRegs/2;
    -
    2495  qreal params[numParams];
    -
    2496 
    -
    2497  // test only if there are an even number of registers
    -
    2498  if (numRegs%2 == 0) {
    -
    2499 
    -
    2500  params[0] = getRandomReal( -10, 10 ); // scaling
    -
    2501  params[1] = getRandomReal( -4, 4 ); // divergence override
    -
    2502  for (int r=0; r<numRegs/2; r++)
    -
    2503  params[2+r] = getRandomReal( -8, 8 ); // shifts
    -
    2504 
    -
    2505  for (size_t i=0; i<diagMatr.size(); i++) {
    -
    2506  qreal phase = 0;
    -
    2507  for (int r=0; r<numRegs; r+=2)
    -
    2508  phase += pow(regVals[i][r+1]-regVals[i][r]-params[2+r/2], 2);
    -
    2509  phase = (phase == 0.)? params[1] : params[0]/sqrt(phase);
    -
    2510  diagMatr[i][i] = expI(phase);
    -
    2511  }
    -
    2512 
    -
    2513  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    -
    2514  }
    -
    2515 
    -
    2516  SECTION( "state-vector" ) {
    -
    2517 
    -
    2518  if (numRegs%2 == 0) {
    -
    2519  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2520  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    -
    2521  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    -
    2522  }
    -
    2523  }
    -
    2524  SECTION( "density-matrix" ) {
    -
    2525 
    -
    2526  if (numRegs%2 == 0) {
    -
    2527  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    -
    2528  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    -
    2529  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    -
    2530  }
    -
    2531  }
    -
    2532  }
    -
    2533  }
    -
    2534  SECTION( "input validation" ) {
    -
    2535 
    -
    2536  int numRegs = 2;
    -
    2537  int numQubitsPerReg[] = {2,3};
    -
    2538  int regs[] = {0,1,2,3,4};
    +
    2073 
    +
    2074 
    +
    2079 TEST_CASE( "applyParamNamedPhaseFuncOverrides", "[operators]" ) {
    +
    2080 
    +
    2081  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    2082 
    +
    2083  SECTION( "correctness" ) {
    +
    2084 
    +
    2085  // try every kind of binary encoding
    +
    2086  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    +
    2087 
    +
    2088  // try every possible number of registers
    +
    2089  // (between #qubits containing 1, and 1 containing #qubits)
    +
    2090  int numRegs;
    +
    2091  int maxNumRegs = 0;
    +
    2092  if (encoding == UNSIGNED)
    +
    2093  maxNumRegs = NUM_QUBITS;
    +
    2094  if (encoding == TWOS_COMPLEMENT)
    +
    2095  maxNumRegs = NUM_QUBITS/2; // floors
    +
    2096  numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
    +
    2097 
    +
    2098  // try every possible total number of involved qubits
    +
    2099  int totalNumQubits;
    +
    2100  int minTotalQubits = 0;
    +
    2101  if (encoding == UNSIGNED)
    +
    2102  // each register must contain at least 1 qubit
    +
    2103  minTotalQubits = numRegs;
    +
    2104  if (encoding == TWOS_COMPLEMENT)
    +
    2105  // each register must contain at least 2 qubits
    +
    2106  minTotalQubits = 2*numRegs;
    +
    2107  totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
    +
    2108 
    +
    2109  // try every qubits subset and ordering
    +
    2110  int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
    +
    2111 
    +
    2112  // assign each sub-reg its minimum length
    +
    2113  int unallocQubits = totalNumQubits;
    +
    2114  int numQubitsPerReg[numRegs];
    +
    2115  for (int i=0; i<numRegs; i++)
    +
    2116  if (encoding == UNSIGNED) {
    +
    2117  numQubitsPerReg[i] = 1;
    +
    2118  unallocQubits -= 1;
    +
    2119  }
    +
    2120  else if (encoding == TWOS_COMPLEMENT) {
    +
    2121  numQubitsPerReg[i] = 2;
    +
    2122  unallocQubits -= 2;
    +
    2123  }
    +
    2124  // and randomly allocate the remaining qubits between the registers
    +
    2125  while (unallocQubits > 0) {
    +
    2126  numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
    +
    2127  unallocQubits--;
    +
    2128  }
    +
    2129 
    +
    2130 
    +
    2131  // choose a random number of overrides (even overriding every amplitude)
    +
    2132  int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
    +
    2133 
    +
    2134  // randomise each override index (uniqueness isn't checked)
    +
    2135  long long int overrideInds[numOverrides*numRegs];
    +
    2136  int flatInd = 0;
    +
    2137  for (int v=0; v<numOverrides; v++) {
    +
    2138  for (int r=0; r<numRegs; r++) {
    +
    2139  if (encoding == UNSIGNED)
    +
    2140  overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
    +
    2141  else if (encoding == TWOS_COMPLEMENT)
    +
    2142  overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
    +
    2143  flatInd++;
    +
    2144  }
    +
    2145  }
    +
    2146 
    +
    2147  // override to a random phase
    +
    2148  qreal overridePhases[numOverrides];
    +
    2149  for (int v=0; v<numOverrides; v++)
    +
    2150  overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    +
    2151 
    +
    2152 
    +
    2153  // determine the values corresponding to each register for all basis states
    +
    2154  qreal regVals[1<<totalNumQubits][numRegs];
    +
    2155  for (long long int i=0; i<(1<<totalNumQubits); i++) {
    +
    2156 
    +
    2157  long long int bits = i;
    +
    2158  for (int r=0; r<numRegs; r++) {
    +
    2159  regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
    +
    2160  bits = bits >> numQubitsPerReg[r];
    +
    2161 
    +
    2162  if (encoding == TWOS_COMPLEMENT)
    +
    2163  regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
    +
    2164  }
    +
    2165  }
    +
    2166 
    +
    2167  /* produce a reference diagonal matrix which assumes the qubits are
    +
    2168  * contiguous and strictly increasing between the registers, and hence
    +
    2169  * only depends on the number of qubits in each register.
    +
    2170  */
    +
    2171  QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
    +
    2172 
    +
    2173 
    +
    2174  SECTION( "INVERSE_NORM" ) {
    +
    2175 
    +
    2176  enum phaseFunc func = INVERSE_NORM;
    +
    2177  qreal divPhase = getRandomReal(-4, 4);
    +
    2178  qreal params[] = {divPhase};
    +
    2179  int numParams = 1;
    +
    2180 
    +
    2181  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2182  qreal phase = 0;
    +
    2183  for (int r=0; r<numRegs; r++)
    +
    2184  phase += pow(regVals[i][r], 2);
    +
    2185  phase = (phase == 0.)? divPhase : 1/sqrt(phase);
    +
    2186  diagMatr[i][i] = expI(phase);
    +
    2187  }
    +
    2188  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2189 
    +
    2190  SECTION( "state-vector" ) {
    +
    2191 
    +
    2192  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2193  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2194  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2195  }
    +
    2196  SECTION( "density-matrix" ) {
    +
    2197 
    +
    2198  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2199  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2200  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2201  }
    +
    2202  }
    +
    2203  SECTION( "SCALED_NORM" ) {
    +
    2204 
    +
    2205  enum phaseFunc func = SCALED_NORM;
    +
    2206  qreal coeff = getRandomReal(-10, 10);
    +
    2207  qreal params[] = {coeff};
    +
    2208  int numParams = 1;
    +
    2209 
    +
    2210  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2211  qreal phase = 0;
    +
    2212  for (int r=0; r<numRegs; r++)
    +
    2213  phase += pow(regVals[i][r], 2);
    +
    2214  phase = coeff * sqrt(phase);
    +
    2215  diagMatr[i][i] = expI(phase);
    +
    2216  }
    +
    2217  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2218 
    +
    2219  SECTION( "state-vector" ) {
    +
    2220 
    +
    2221  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2222  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2223  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2224  }
    +
    2225  SECTION( "density-matrix" ) {
    +
    2226 
    +
    2227  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2228  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2229  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2230  }
    +
    2231  }
    +
    2232  SECTION( "SCALED_INVERSE_NORM" ) {
    +
    2233 
    +
    2234  enum phaseFunc func = SCALED_INVERSE_NORM;
    +
    2235  qreal coeff = getRandomReal(-10, 10);
    +
    2236  qreal divPhase = getRandomReal(-4, 4);
    +
    2237  qreal params[] = {coeff, divPhase};
    +
    2238  int numParams = 2;
    +
    2239 
    +
    2240  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2241  qreal phase = 0;
    +
    2242  for (int r=0; r<numRegs; r++)
    +
    2243  phase += pow(regVals[i][r], 2);
    +
    2244  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    +
    2245  diagMatr[i][i] = expI(phase);
    +
    2246  }
    +
    2247  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2248 
    +
    2249  SECTION( "state-vector" ) {
    +
    2250 
    +
    2251  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2252  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2253  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2254  }
    +
    2255  SECTION( "density-matrix" ) {
    +
    2256 
    +
    2257  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2258  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2259  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2260  }
    +
    2261  }
    +
    2262  SECTION( "SCALED_INVERSE_SHIFTED_NORM" ) {
    +
    2263 
    + +
    2265  int numParams = 2 + numRegs;
    +
    2266  qreal params[numParams];
    +
    2267  params[0] = getRandomReal(-10, 10); // scaling
    +
    2268  params[1] = getRandomReal(-4, 4); // divergence override
    +
    2269  for (int r=0; r<numRegs; r++)
    +
    2270  params[2+r] = getRandomReal(-8, 8); // shifts
    +
    2271 
    +
    2272  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2273  qreal phase = 0;
    +
    2274  for (int r=0; r<numRegs; r++)
    +
    2275  phase += pow(regVals[i][r] - params[2+r], 2);
    +
    2276  phase = sqrt(phase);
    +
    2277  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    2278  diagMatr[i][i] = expI(phase);
    +
    2279  }
    +
    2280  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2281 
    +
    2282  SECTION( "state-vector" ) {
    +
    2283 
    +
    2284  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2285  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2286  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2287  }
    +
    2288  SECTION( "density-matrix" ) {
    +
    2289 
    +
    2290  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2291  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2292  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2293  }
    +
    2294  }
    +
    2295  SECTION( "INVERSE_PRODUCT" ) {
    +
    2296 
    +
    2297  enum phaseFunc func = INVERSE_PRODUCT;
    +
    2298  qreal divPhase = getRandomReal(-4, 4);
    +
    2299  qreal params[] = {divPhase};
    +
    2300  int numParams = 1;
    +
    2301 
    +
    2302  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2303  qreal phase = 1;
    +
    2304  for (int r=0; r<numRegs; r++)
    +
    2305  phase *= regVals[i][r];
    +
    2306  phase = (phase == 0.)? divPhase : 1. / phase;
    +
    2307  diagMatr[i][i] = expI(phase);
    +
    2308  }
    +
    2309  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2310 
    +
    2311  SECTION( "state-vector" ) {
    +
    2312 
    +
    2313  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2314  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2315  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2316  }
    +
    2317  SECTION( "density-matrix" ) {
    +
    2318 
    +
    2319  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2320  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2321  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2322  }
    +
    2323  }
    +
    2324  SECTION( "SCALED_PRODUCT" ) {
    +
    2325 
    +
    2326  enum phaseFunc func = SCALED_PRODUCT;
    +
    2327  qreal coeff = getRandomReal(-10, 10);
    +
    2328  qreal params[] = {coeff};
    +
    2329  int numParams = 1;
    +
    2330 
    +
    2331  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2332  qreal phase = 1;
    +
    2333  for (int r=0; r<numRegs; r++)
    +
    2334  phase *= regVals[i][r];
    +
    2335  diagMatr[i][i] = expI(coeff * phase);
    +
    2336  }
    +
    2337  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2338 
    +
    2339  SECTION( "state-vector" ) {
    +
    2340 
    +
    2341  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2342  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2343  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2344  }
    +
    2345  SECTION( "density-matrix" ) {
    +
    2346 
    +
    2347  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2348  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2349  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2350  }
    +
    2351  }
    +
    2352  SECTION( "SCALED_INVERSE_PRODUCT" ) {
    +
    2353 
    +
    2354  enum phaseFunc func = SCALED_INVERSE_PRODUCT;
    +
    2355  qreal coeff = getRandomReal(-10, 10);
    +
    2356  qreal divPhase = getRandomReal(-4, 4);
    +
    2357  qreal params[] = {coeff, divPhase};
    +
    2358  int numParams = 2;
    +
    2359 
    +
    2360  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2361  qreal phase = 1;
    +
    2362  for (int r=0; r<numRegs; r++)
    +
    2363  phase *= regVals[i][r];
    +
    2364  phase = (phase == 0)? divPhase : coeff / phase;
    +
    2365  diagMatr[i][i] = expI(phase);
    +
    2366  }
    +
    2367  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2368 
    +
    2369  SECTION( "state-vector" ) {
    +
    2370 
    +
    2371  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2372  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2373  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2374  }
    +
    2375  SECTION( "density-matrix" ) {
    +
    2376 
    +
    2377  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2378  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2379  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2380  }
    +
    2381  }
    +
    2382  SECTION( "INVERSE_DISTANCE" ) {
    +
    2383 
    +
    2384  enum phaseFunc func = INVERSE_DISTANCE;
    +
    2385  qreal divPhase = getRandomReal( -4, 4 );
    +
    2386  qreal params[] = {divPhase};
    +
    2387  int numParams = 1;
    +
    2388 
    +
    2389  // test only if there are an even number of registers
    +
    2390  if (numRegs%2 == 0) {
    +
    2391 
    +
    2392  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2393  qreal phase = 0;
    +
    2394  for (int r=0; r<numRegs; r+=2)
    +
    2395  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    2396  phase = (phase == 0.)? divPhase : 1./sqrt(phase);
    +
    2397  diagMatr[i][i] = expI(phase);
    +
    2398  }
    +
    2399  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2400  }
    +
    2401 
    +
    2402  SECTION( "state-vector" ) {
    +
    2403 
    +
    2404  if (numRegs%2 == 0) {
    +
    2405  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2406  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2407  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2408  }
    +
    2409  }
    +
    2410  SECTION( "density-matrix" ) {
    +
    2411 
    +
    2412  if (numRegs%2 == 0) {
    +
    2413  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2414  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2415  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2416  }
    +
    2417  }
    +
    2418  }
    +
    2419  SECTION( "SCALED_DISTANCE" ) {
    +
    2420 
    +
    2421  enum phaseFunc func = SCALED_DISTANCE;
    +
    2422  qreal coeff = getRandomReal( -10, 10 );
    +
    2423  qreal params[] = {coeff};
    +
    2424  int numParams = 1;
    +
    2425 
    +
    2426  // test only if there are an even number of registers
    +
    2427  if (numRegs%2 == 0) {
    +
    2428 
    +
    2429  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2430  qreal phase = 0;
    +
    2431  for (int r=0; r<numRegs; r+=2)
    +
    2432  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    2433  phase = coeff * sqrt(phase);
    +
    2434  diagMatr[i][i] = expI(phase);
    +
    2435  }
    +
    2436  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2437  }
    +
    2438 
    +
    2439  SECTION( "state-vector" ) {
    +
    2440 
    +
    2441  if (numRegs%2 == 0) {
    +
    2442  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2443  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2444  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2445  }
    +
    2446  }
    +
    2447  SECTION( "density-matrix" ) {
    +
    2448 
    +
    2449  if (numRegs%2 == 0) {
    +
    2450  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2451  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2452  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2453  }
    +
    2454  }
    +
    2455  }
    +
    2456  SECTION( "SCALED_INVERSE_DISTANCE" ) {
    +
    2457 
    +
    2458  enum phaseFunc func = SCALED_INVERSE_DISTANCE;
    +
    2459  qreal coeff = getRandomReal( -10, 10 );
    +
    2460  qreal divPhase = getRandomReal( -4, 4 );
    +
    2461  qreal params[] = {coeff, divPhase};
    +
    2462  int numParams = 2;
    +
    2463 
    +
    2464  // test only if there are an even number of registers
    +
    2465  if (numRegs%2 == 0) {
    +
    2466 
    +
    2467  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2468  qreal phase = 0;
    +
    2469  for (int r=0; r<numRegs; r+=2)
    +
    2470  phase += pow(regVals[i][r+1]-regVals[i][r], 2);
    +
    2471  phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
    +
    2472  diagMatr[i][i] = expI(phase);
    +
    2473  }
    +
    2474  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2475  }
    +
    2476 
    +
    2477  SECTION( "state-vector" ) {
    +
    2478 
    +
    2479  if (numRegs%2 == 0) {
    +
    2480  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2481  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2482  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2483  }
    +
    2484  }
    +
    2485  SECTION( "density-matrix" ) {
    +
    2486 
    +
    2487  if (numRegs%2 == 0) {
    +
    2488  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2489  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2490  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2491  }
    +
    2492  }
    +
    2493  }
    +
    2494  SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
    +
    2495 
    + +
    2497  int numParams = 2 + numRegs/2;
    +
    2498  qreal params[numParams];
    +
    2499 
    +
    2500  // test only if there are an even number of registers
    +
    2501  if (numRegs%2 == 0) {
    +
    2502 
    +
    2503  params[0] = getRandomReal( -10, 10 ); // scaling
    +
    2504  params[1] = getRandomReal( -4, 4 ); // divergence override
    +
    2505  for (int r=0; r<numRegs/2; r++)
    +
    2506  params[2+r] = getRandomReal( -8, 8 ); // shifts
    +
    2507 
    +
    2508  for (size_t i=0; i<diagMatr.size(); i++) {
    +
    2509  qreal phase = 0;
    +
    2510  for (int r=0; r<numRegs; r+=2)
    +
    2511  phase += pow(regVals[i][r]-regVals[i][r+1]-params[2+r/2], 2);
    +
    2512  phase = sqrt(phase);
    +
    2513  phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
    +
    2514  diagMatr[i][i] = expI(phase);
    +
    2515  }
    +
    2516 
    +
    2517  setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
    +
    2518  }
    +
    2519 
    +
    2520  SECTION( "state-vector" ) {
    +
    2521 
    +
    2522  if (numRegs%2 == 0) {
    +
    2523  applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2524  applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
    +
    2525  REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
    +
    2526  }
    +
    2527  }
    +
    2528  SECTION( "density-matrix" ) {
    +
    2529 
    +
    2530  if (numRegs%2 == 0) {
    +
    2531  applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
    +
    2532  applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
    +
    2533  REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
    +
    2534  }
    +
    2535  }
    +
    2536  }
    +
    2537  }
    +
    2538  SECTION( "input validation" ) {
    2539 
    -
    2540  SECTION( "number of registers" ) {
    -
    2541 
    -
    2542  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    -
    2543  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubit subregisters") );
    -
    2544  }
    -
    2545  SECTION( "number of qubits" ) {
    -
    2546 
    -
    2547  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    -
    2548  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubits") );
    -
    2549  }
    -
    2550  SECTION( "repetition of qubits" ) {
    -
    2551 
    -
    2552  regs[GENERATE(2,3,4)] = regs[1];
    -
    2553  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("The qubits must be unique") );
    -
    2554  }
    -
    2555  SECTION( "qubit indices" ) {
    -
    2556 
    -
    2557  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    -
    2558  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid qubit index") );
    -
    2559  }
    -
    2560  SECTION( "bit encoding name" ) {
    -
    2561 
    -
    2562  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    -
    2563  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid bit encoding") );
    -
    2564  }
    -
    2565  SECTION( "two's complement register" ) {
    -
    2566 
    -
    2567  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    -
    2568  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0, NULL, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    -
    2569  }
    -
    2570  SECTION( "phase function name" ) {
    -
    2571 
    -
    2572  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    -
    2573  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0, NULL, NULL, 0), Contains("Invalid named phase function") );
    -
    2574  }
    -
    2575  SECTION( "phase function parameters" ) {
    -
    2576 
    -
    2577  qreal params[numRegs + 3];
    -
    2578  for (int r=0; r<numRegs + 3; r++)
    -
    2579  params[r] = 0;
    +
    2540  int numRegs = 2;
    +
    2541  int numQubitsPerReg[] = {2,3};
    +
    2542  int regs[] = {0,1,2,3,4};
    +
    2543 
    +
    2544  SECTION( "number of registers" ) {
    +
    2545 
    +
    2546  numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
    +
    2547  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubit subregisters") );
    +
    2548  }
    +
    2549  SECTION( "number of qubits" ) {
    +
    2550 
    +
    2551  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
    +
    2552  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid number of qubits") );
    +
    2553  }
    +
    2554  SECTION( "repetition of qubits" ) {
    +
    2555 
    +
    2556  regs[GENERATE(2,3,4)] = regs[1];
    +
    2557  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("The qubits must be unique") );
    +
    2558  }
    +
    2559  SECTION( "qubit indices" ) {
    +
    2560 
    +
    2561  regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
    +
    2562  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid qubit index") );
    +
    2563  }
    +
    2564  SECTION( "bit encoding name" ) {
    +
    2565 
    +
    2566  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
    +
    2567  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, NULL, NULL, 0), Contains("Invalid bit encoding") );
    +
    2568  }
    +
    2569  SECTION( "two's complement register" ) {
    +
    2570 
    +
    2571  numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
    +
    2572  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0, NULL, NULL, 0), Contains("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
    +
    2573  }
    +
    2574  SECTION( "phase function name" ) {
    +
    2575 
    +
    2576  enum phaseFunc func = (enum phaseFunc) GENERATE( -1, 14 );
    +
    2577  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0, NULL, NULL, 0), Contains("Invalid named phase function") );
    +
    2578  }
    +
    2579  SECTION( "phase function parameters" ) {
    2580 
    -
    2581  SECTION( "no parameter functions" ) {
    -
    2582 
    -
    2583  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    -
    2584  int numParams = GENERATE( -1, 1, 2 );
    -
    2585  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2586  }
    -
    2587  SECTION( "single parameter functions" ) {
    -
    2588 
    - -
    2590  int numParams = GENERATE( -1, 0, 2 );
    -
    2591  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2592  }
    -
    2593  SECTION( "two parameter functions" ) {
    -
    2594 
    - -
    2596  int numParams = GENERATE( 0, 1, 3 );
    -
    2597  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2598  }
    -
    2599  SECTION( "shifted distance" ) {
    -
    2600 
    -
    2601  if (numRegs%2 == 0) {
    - -
    2603  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    -
    2604  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2605  }
    -
    2606  }
    -
    2607  SECTION( "shifted norm" ) {
    -
    2608 
    - -
    2610  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    -
    2611  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    -
    2612  }
    -
    2613  }
    -
    2614  SECTION( "distance pair registers" ) {
    -
    2615 
    -
    2616  int numQb[] = {1,1,1,1,1};
    -
    2617  int qb[] = {0,1,2,3,4};
    -
    2618 
    -
    2619  numRegs = GENERATE( 1, 3, 5 );
    -
    2620  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0, NULL, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    -
    2621  }
    -
    2622  SECTION( "number of overrides" ) {
    -
    2623 
    -
    2624  int numOverrides = -1;
    -
    2625  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides specified") );
    -
    2626  }
    -
    2627  SECTION( "override indices" ) {
    -
    2628 
    -
    2629  // numQubitsPerReg = {2, 3}
    -
    2630  int numOverrides = 3;
    -
    2631  long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
    -
    2632  qreal overridePhases[] = {.1, .1, .1};
    -
    2633 
    -
    2634  // first element of overrideInds coordinate is a 2 qubit register
    -
    2635  enum bitEncoding enc = UNSIGNED;
    -
    2636  int badInd = GENERATE(0, 2, 4);
    -
    2637  overrideInds[badInd] = GENERATE( -1, (1<<2) );
    -
    2638  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    -
    2639  overrideInds[badInd] = 0;
    -
    2640 
    -
    2641  // second element of overrideInds coordinate is a 3 qubit register
    -
    2642  badInd += 1;
    -
    2643  overrideInds[badInd] = GENERATE( -1, (1<<3) );
    -
    2644  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    -
    2645  overrideInds[badInd] = 0;
    -
    2646  badInd -= 1;
    -
    2647 
    -
    2648  enc = TWOS_COMPLEMENT;
    -
    2649  int minInd = -(1<<(numQubitsPerReg[0]-1));
    -
    2650  int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
    -
    2651  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    -
    2652  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    -
    2653  overrideInds[badInd] = 0;
    -
    2654 
    -
    2655  badInd++;
    -
    2656  minInd = -(1<<(numQubitsPerReg[1]-1));
    -
    2657  maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
    -
    2658  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    -
    2659  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    -
    2660  }
    -
    2661  }
    -
    2662  CLEANUP_TEST( quregVec, quregMatr );
    -
    2663 }
    -
    2664 
    -
    2665 
    -
    2666 
    -
    2671 TEST_CASE( "applyPauliHamil", "[operators]" ) {
    -
    2672 
    - - - - -
    2677 
    -
    2678  initDebugState(vecIn);
    -
    2679  initDebugState(matIn);
    -
    2680 
    -
    2681  SECTION( "correctness" ) {
    -
    2682 
    -
    2683  /* it's too expensive to try every possible Pauli configuration, so
    -
    2684  * we'll try 10 random codes, and for each, random coefficients
    -
    2685  */
    -
    2686  GENERATE( range(0,10) );
    -
    2687 
    -
    2688  int numTerms = GENERATE( 1, 2, 10, 15 );
    -
    2689  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    2690  setRandomPauliSum(hamil);
    -
    2691  QMatrix refHamil = toQMatrix(hamil);
    -
    2692 
    -
    2693  SECTION( "state-vector" ) {
    -
    2694 
    -
    2695  QVector vecRef = toQVector(vecIn);
    -
    2696  applyPauliHamil(vecIn, hamil, vecOut);
    -
    2697 
    -
    2698  // ensure vecIn barely changes under precision
    -
    2699  REQUIRE( areEqual(vecIn, vecRef) );
    -
    2700 
    -
    2701  // ensure vecOut changed correctly
    -
    2702  REQUIRE( areEqual(vecOut, refHamil * vecRef) );
    -
    2703  }
    -
    2704  SECTION( "density-matrix" ) {
    -
    2705 
    -
    2706  QMatrix matRef = toQMatrix(matIn);
    -
    2707  applyPauliHamil(matIn, hamil, matOut);
    -
    2708 
    -
    2709  // ensure matIn barely changes under precision
    -
    2710  REQUIRE( areEqual(matIn, matRef) );
    -
    2711 
    -
    2712  // ensure matOut changed correctly
    -
    2713  REQUIRE( areEqual(matOut, refHamil * matRef, 1E2*REAL_EPS) );
    -
    2714  }
    -
    2715 
    -
    2716  destroyPauliHamil(hamil);
    -
    2717  }
    -
    2718  SECTION( "input validation" ) {
    +
    2581  qreal params[numRegs + 3];
    +
    2582  for (int r=0; r<numRegs + 3; r++)
    +
    2583  params[r] = 0;
    +
    2584 
    +
    2585  SECTION( "no parameter functions" ) {
    +
    2586 
    +
    2587  enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
    +
    2588  int numParams = GENERATE( -1, 1, 2 );
    +
    2589  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2590  }
    +
    2591  SECTION( "single parameter functions" ) {
    +
    2592 
    + +
    2594  int numParams = GENERATE( -1, 0, 2 );
    +
    2595  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2596  }
    +
    2597  SECTION( "two parameter functions" ) {
    +
    2598 
    + +
    2600  int numParams = GENERATE( 0, 1, 3 );
    +
    2601  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2602  }
    +
    2603  SECTION( "shifted distance" ) {
    +
    2604 
    +
    2605  if (numRegs%2 == 0) {
    + +
    2607  int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
    +
    2608  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2609  }
    +
    2610  }
    +
    2611  SECTION( "shifted norm" ) {
    +
    2612 
    + +
    2614  int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
    +
    2615  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), Contains("Invalid number of parameters") );
    +
    2616  }
    +
    2617  }
    +
    2618  SECTION( "distance pair registers" ) {
    +
    2619 
    +
    2620  int numQb[] = {1,1,1,1,1};
    +
    2621  int qb[] = {0,1,2,3,4};
    +
    2622 
    +
    2623  numRegs = GENERATE( 1, 3, 5 );
    +
    2624  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0, NULL, NULL, 0), Contains("Phase functions DISTANCE") && Contains("even number of sub-registers") );
    +
    2625  }
    +
    2626  SECTION( "number of overrides" ) {
    +
    2627 
    +
    2628  int numOverrides = -1;
    +
    2629  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides specified") );
    +
    2630  }
    +
    2631  SECTION( "override indices" ) {
    +
    2632 
    +
    2633  // numQubitsPerReg = {2, 3}
    +
    2634  int numOverrides = 3;
    +
    2635  long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
    +
    2636  qreal overridePhases[] = {.1, .1, .1};
    +
    2637 
    +
    2638  // first element of overrideInds coordinate is a 2 qubit register
    +
    2639  enum bitEncoding enc = UNSIGNED;
    +
    2640  int badInd = GENERATE(0, 2, 4);
    +
    2641  overrideInds[badInd] = GENERATE( -1, (1<<2) );
    +
    2642  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    2643  overrideInds[badInd] = 0;
    +
    2644 
    +
    2645  // second element of overrideInds coordinate is a 3 qubit register
    +
    2646  badInd += 1;
    +
    2647  overrideInds[badInd] = GENERATE( -1, (1<<3) );
    +
    2648  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    2649  overrideInds[badInd] = 0;
    +
    2650  badInd -= 1;
    +
    2651 
    +
    2652  enc = TWOS_COMPLEMENT;
    +
    2653  int minInd = -(1<<(numQubitsPerReg[0]-1));
    +
    2654  int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
    +
    2655  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    +
    2656  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    +
    2657  overrideInds[badInd] = 0;
    +
    2658 
    +
    2659  badInd++;
    +
    2660  minInd = -(1<<(numQubitsPerReg[1]-1));
    +
    2661  maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
    +
    2662  overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
    +
    2663  REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    +
    2664  }
    +
    2665  }
    +
    2666  CLEANUP_TEST( quregVec, quregMatr );
    +
    2667 }
    +
    2668 
    +
    2669 
    +
    2670 
    +
    2675 TEST_CASE( "applyPauliHamil", "[operators]" ) {
    +
    2676 
    + + + + +
    2681 
    +
    2682  initDebugState(vecIn);
    +
    2683  initDebugState(matIn);
    +
    2684 
    +
    2685  SECTION( "correctness" ) {
    +
    2686 
    +
    2687  /* it's too expensive to try every possible Pauli configuration, so
    +
    2688  * we'll try 10 random codes, and for each, random coefficients
    +
    2689  */
    +
    2690  GENERATE( range(0,10) );
    +
    2691 
    +
    2692  int numTerms = GENERATE( 1, 2, 10, 15 );
    +
    2693  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    +
    2694  setRandomPauliSum(hamil);
    +
    2695  QMatrix refHamil = toQMatrix(hamil);
    +
    2696 
    +
    2697  SECTION( "state-vector" ) {
    +
    2698 
    +
    2699  QVector vecRef = toQVector(vecIn);
    +
    2700  applyPauliHamil(vecIn, hamil, vecOut);
    +
    2701 
    +
    2702  // ensure vecIn barely changes under precision
    +
    2703  REQUIRE( areEqual(vecIn, vecRef) );
    +
    2704 
    +
    2705  // ensure vecOut changed correctly
    +
    2706  REQUIRE( areEqual(vecOut, refHamil * vecRef) );
    +
    2707  }
    +
    2708  SECTION( "density-matrix" ) {
    +
    2709 
    +
    2710  QMatrix matRef = toQMatrix(matIn);
    +
    2711  applyPauliHamil(matIn, hamil, matOut);
    +
    2712 
    +
    2713  // ensure matIn barely changes under precision
    +
    2714  REQUIRE( areEqual(matIn, matRef) );
    +
    2715 
    +
    2716  // ensure matOut changed correctly
    +
    2717  REQUIRE( areEqual(matOut, refHamil * matRef, 1E2*REAL_EPS) );
    +
    2718  }
    2719 
    -
    2720  SECTION( "pauli codes" ) {
    -
    2721 
    -
    2722  int numTerms = 3;
    -
    2723  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    2724 
    -
    2725  // make one pauli code wrong
    -
    2726  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    2727  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("Invalid Pauli code") );
    -
    2728 
    -
    2729  destroyPauliHamil(hamil);
    -
    2730  }
    -
    2731  SECTION( "qureg dimensions" ) {
    +
    2720  destroyPauliHamil(hamil);
    +
    2721  }
    +
    2722  SECTION( "input validation" ) {
    +
    2723 
    +
    2724  SECTION( "pauli codes" ) {
    +
    2725 
    +
    2726  int numTerms = 3;
    +
    2727  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    +
    2728 
    +
    2729  // make one pauli code wrong
    +
    2730  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    +
    2731  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("Invalid Pauli code") );
    2732 
    -
    2733  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    - -
    2735 
    -
    2736  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, badVec), Contains("Dimensions of the qubit registers don't match") );
    -
    2737 
    -
    2738  destroyQureg(badVec, QUEST_ENV);
    -
    2739  destroyPauliHamil(hamil);
    -
    2740  }
    -
    2741  SECTION( "qureg types" ) {
    -
    2742 
    - -
    2744 
    -
    2745  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    +
    2733  destroyPauliHamil(hamil);
    +
    2734  }
    +
    2735  SECTION( "qureg dimensions" ) {
    +
    2736 
    +
    2737  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    + +
    2739 
    +
    2740  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, badVec), Contains("Dimensions of the qubit registers don't match") );
    +
    2741 
    +
    2742  destroyQureg(badVec, QUEST_ENV);
    +
    2743  destroyPauliHamil(hamil);
    +
    2744  }
    +
    2745  SECTION( "qureg types" ) {
    2746 
    -
    2747  destroyPauliHamil(hamil);
    -
    2748  }
    -
    2749  SECTION( "matching hamiltonian qubits" ) {
    + +
    2748 
    +
    2749  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    2750 
    -
    2751  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    -
    2752 
    -
    2753  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("same number of qubits") );
    -
    2754  REQUIRE_THROWS_WITH( applyPauliHamil(matIn, hamil, matOut), Contains("same number of qubits") );
    -
    2755 
    -
    2756  destroyPauliHamil(hamil);
    -
    2757  }
    -
    2758  }
    -
    2759  destroyQureg(vecIn, QUEST_ENV);
    -
    2760  destroyQureg(vecOut, QUEST_ENV);
    -
    2761  destroyQureg(matIn, QUEST_ENV);
    -
    2762  destroyQureg(matOut, QUEST_ENV);
    -
    2763 }
    -
    2764 
    -
    2765 
    -
    2766 
    -
    2771 TEST_CASE( "applyPauliSum", "[operators]" ) {
    -
    2772 
    - - - - -
    2777 
    -
    2778  initDebugState(vecIn);
    -
    2779  initDebugState(matIn);
    -
    2780 
    -
    2781  SECTION( "correctness" ) {
    -
    2782 
    -
    2783  /* it's too expensive to try ALL Pauli sequences, via
    -
    2784  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
    -
    2785  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    -
    2786  * Hence, we instead opt to repeatedly randomly generate pauliseqs
    -
    2787  */
    -
    2788  GENERATE( range(0,10) ); // gen 10 random pauli-codes
    -
    2789 
    -
    2790  int numTerms = GENERATE( 1, 2, 10, 15);
    -
    2791  int numPaulis = numTerms * NUM_QUBITS;
    -
    2792 
    -
    2793  // each test will use random coefficients
    -
    2794  qreal coeffs[numTerms];
    -
    2795  pauliOpType paulis[numPaulis];
    -
    2796  setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numTerms);
    -
    2797  QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numTerms);
    -
    2798 
    -
    2799  SECTION( "state-vector" ) {
    -
    2800 
    -
    2801  QVector vecRef = toQVector(vecIn);
    -
    2802  applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
    -
    2803 
    -
    2804  // ensure vecIn barely changes under precision
    -
    2805  REQUIRE( areEqual(vecIn, vecRef) );
    -
    2806 
    -
    2807  // ensure vecOut changed correctly
    -
    2808  REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
    -
    2809  }
    -
    2810  SECTION( "density-matrix" ) {
    -
    2811 
    -
    2812  QMatrix matRef = toQMatrix(matIn);
    -
    2813  applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
    -
    2814 
    -
    2815  // ensure matIn barely changes under precision
    -
    2816  REQUIRE( areEqual(matIn, matRef) );
    -
    2817 
    -
    2818  // ensure matOut changed correctly
    -
    2819  REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
    -
    2820  }
    -
    2821  }
    -
    2822  SECTION( "input validation" ) {
    -
    2823 
    -
    2824  SECTION( "number of terms" ) {
    -
    2825 
    -
    2826  int numTerms = GENERATE( -1, 0 );
    -
    2827  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), Contains("Invalid number of terms") );
    -
    2828  }
    -
    2829  SECTION( "pauli codes" ) {
    -
    2830 
    -
    2831  // valid codes
    -
    2832  int numTerms = 3;
    -
    2833  int numPaulis = numTerms*NUM_QUBITS;
    -
    2834  pauliOpType paulis[numPaulis];
    -
    2835  for (int i=0; i<numPaulis; i++)
    -
    2836  paulis[i] = PAULI_I;
    -
    2837 
    -
    2838  // make one invalid
    -
    2839  paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    2840  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), Contains("Invalid Pauli code") );
    -
    2841  }
    -
    2842  SECTION( "qureg dimensions" ) {
    -
    2843 
    -
    2844  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    -
    2845  pauliOpType paulis[NUM_QUBITS];
    -
    2846  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), Contains("Dimensions of the qubit registers don't match") );
    -
    2847  destroyQureg(badVec, QUEST_ENV);
    -
    2848  }
    -
    2849  SECTION( "qureg types" ) {
    -
    2850 
    -
    2851  pauliOpType paulis[NUM_QUBITS];
    -
    2852  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    -
    2853  }
    -
    2854  }
    -
    2855  destroyQureg(vecIn, QUEST_ENV);
    -
    2856  destroyQureg(vecOut, QUEST_ENV);
    -
    2857  destroyQureg(matIn, QUEST_ENV);
    -
    2858  destroyQureg(matOut, QUEST_ENV);
    -
    2859 }
    -
    2860 
    -
    2861 
    -
    2862 
    -
    2867 TEST_CASE( "applyPhaseFunc", "[operators]" ) {
    -
    2868 
    -
    2869  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    2870 
    -
    2871  SECTION( "correctness" ) {
    -
    2872 
    -
    2873  // try every kind of binary encodings
    -
    2874  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    -
    2875 
    -
    2876  // try every sub-register size
    -
    2877  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    -
    2878 
    -
    2879  // force at least 2 qubits in two's compement though
    -
    2880  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    -
    2881  numQubits++;
    +
    2751  destroyPauliHamil(hamil);
    +
    2752  }
    +
    2753  SECTION( "matching hamiltonian qubits" ) {
    +
    2754 
    +
    2755  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    +
    2756 
    +
    2757  REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), Contains("same number of qubits") );
    +
    2758  REQUIRE_THROWS_WITH( applyPauliHamil(matIn, hamil, matOut), Contains("same number of qubits") );
    +
    2759 
    +
    2760  destroyPauliHamil(hamil);
    +
    2761  }
    +
    2762  }
    +
    2763  destroyQureg(vecIn, QUEST_ENV);
    +
    2764  destroyQureg(vecOut, QUEST_ENV);
    +
    2765  destroyQureg(matIn, QUEST_ENV);
    +
    2766  destroyQureg(matOut, QUEST_ENV);
    +
    2767 }
    +
    2768 
    +
    2769 
    +
    2770 
    +
    2775 TEST_CASE( "applyPauliSum", "[operators]" ) {
    +
    2776 
    + + + + +
    2781 
    +
    2782  initDebugState(vecIn);
    +
    2783  initDebugState(matIn);
    +
    2784 
    +
    2785  SECTION( "correctness" ) {
    +
    2786 
    +
    2787  /* it's too expensive to try ALL Pauli sequences, via
    +
    2788  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
    +
    2789  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
    +
    2790  * Hence, we instead opt to repeatedly randomly generate pauliseqs
    +
    2791  */
    +
    2792  GENERATE( range(0,10) ); // gen 10 random pauli-codes
    +
    2793 
    +
    2794  int numTerms = GENERATE( 1, 2, 10, 15);
    +
    2795  int numPaulis = numTerms * NUM_QUBITS;
    +
    2796 
    +
    2797  // each test will use random coefficients
    +
    2798  qreal coeffs[numTerms];
    +
    2799  pauliOpType paulis[numPaulis];
    +
    2800  setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numTerms);
    +
    2801  QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numTerms);
    +
    2802 
    +
    2803  SECTION( "state-vector" ) {
    +
    2804 
    +
    2805  QVector vecRef = toQVector(vecIn);
    +
    2806  applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
    +
    2807 
    +
    2808  // ensure vecIn barely changes under precision
    +
    2809  REQUIRE( areEqual(vecIn, vecRef) );
    +
    2810 
    +
    2811  // ensure vecOut changed correctly
    +
    2812  REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
    +
    2813  }
    +
    2814  SECTION( "density-matrix" ) {
    +
    2815 
    +
    2816  QMatrix matRef = toQMatrix(matIn);
    +
    2817  applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
    +
    2818 
    +
    2819  // ensure matIn barely changes under precision
    +
    2820  REQUIRE( areEqual(matIn, matRef) );
    +
    2821 
    +
    2822  // ensure matOut changed correctly
    +
    2823  REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
    +
    2824  }
    +
    2825  }
    +
    2826  SECTION( "input validation" ) {
    +
    2827 
    +
    2828  SECTION( "number of terms" ) {
    +
    2829 
    +
    2830  int numTerms = GENERATE( -1, 0 );
    +
    2831  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), Contains("Invalid number of terms") );
    +
    2832  }
    +
    2833  SECTION( "pauli codes" ) {
    +
    2834 
    +
    2835  // valid codes
    +
    2836  int numTerms = 3;
    +
    2837  int numPaulis = numTerms*NUM_QUBITS;
    +
    2838  pauliOpType paulis[numPaulis];
    +
    2839  for (int i=0; i<numPaulis; i++)
    +
    2840  paulis[i] = PAULI_I;
    +
    2841 
    +
    2842  // make one invalid
    +
    2843  paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
    +
    2844  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), Contains("Invalid Pauli code") );
    +
    2845  }
    +
    2846  SECTION( "qureg dimensions" ) {
    +
    2847 
    +
    2848  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
    +
    2849  pauliOpType paulis[NUM_QUBITS];
    +
    2850  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), Contains("Dimensions of the qubit registers don't match") );
    +
    2851  destroyQureg(badVec, QUEST_ENV);
    +
    2852  }
    +
    2853  SECTION( "qureg types" ) {
    +
    2854 
    +
    2855  pauliOpType paulis[NUM_QUBITS];
    +
    2856  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
    +
    2857  }
    +
    2858  }
    +
    2859  destroyQureg(vecIn, QUEST_ENV);
    +
    2860  destroyQureg(vecOut, QUEST_ENV);
    +
    2861  destroyQureg(matIn, QUEST_ENV);
    +
    2862  destroyQureg(matOut, QUEST_ENV);
    +
    2863 }
    +
    2864 
    +
    2865 
    +
    2866 
    +
    2871 TEST_CASE( "applyPhaseFunc", "[operators]" ) {
    +
    2872 
    +
    2873  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    2874 
    +
    2875  SECTION( "correctness" ) {
    +
    2876 
    +
    2877  // try every kind of binary encodings
    +
    2878  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    +
    2879 
    +
    2880  // try every sub-register size
    +
    2881  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    2882 
    -
    2883  // try every possible sub-register
    -
    2884  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    -
    2885 
    -
    2886  // choose a random number of terms in the phase function
    -
    2887  int numTerms = getRandomInt(1, 5);
    -
    2888 
    -
    2889  // populate the phase function with random but POSITIVE-power terms,
    -
    2890  // and in two's complement mode, strictly integer powers
    -
    2891  qreal coeffs[numTerms];
    -
    2892  qreal expons[numTerms];
    -
    2893  for (int t=0; t<numTerms; t++) {
    -
    2894  coeffs[t] = getRandomReal(-10,10);
    -
    2895  if (encoding == TWOS_COMPLEMENT)
    -
    2896  expons[t] = getRandomInt(0, 3+1); // repetition of power is ok
    -
    2897  else
    -
    2898  expons[t] = getRandomReal(0, 3);
    -
    2899  }
    -
    2900 
    -
    2901  // build a reference diagonal matrix, on the reduced Hilbert space
    -
    2902  QMatrix matr = getZeroMatrix( 1 << numQubits );
    -
    2903  for (size_t i=0; i<matr.size(); i++) {
    -
    2904 
    -
    2905  long long int ind = 0;
    -
    2906  if (encoding == UNSIGNED)
    -
    2907  ind = i;
    -
    2908  if (encoding == TWOS_COMPLEMENT)
    -
    2909  ind = getTwosComplement(i, numQubits);
    -
    2910 
    -
    2911  qreal phase = 0;
    -
    2912  for (int t=0; t<numTerms; t++)
    -
    2913  phase += coeffs[t] * pow(ind, expons[t]);
    -
    2914 
    -
    2915  matr[i][i] = expI(phase);
    -
    2916  }
    -
    2917 
    -
    2918  SECTION( "state-vector" ) {
    -
    2919 
    -
    2920  applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms);
    -
    2921  applyReferenceOp(refVec, qubits, numQubits, matr);
    -
    2922  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    -
    2923  }
    -
    2924  SECTION( "density-matrix" ) {
    -
    2925 
    -
    2926  applyPhaseFunc(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms);
    -
    2927  applyReferenceOp(refMatr, qubits, numQubits, matr);
    -
    2928  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    -
    2929  }
    -
    2930  }
    -
    2931  SECTION( "input validation" ) {
    -
    2932 
    -
    2933  int numQubits = 3;
    -
    2934  int qubits[] = {0,1,2};
    -
    2935 
    -
    2936  SECTION( "number of qubits" ) {
    -
    2937 
    -
    2938  numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    -
    2939  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid number of qubits") );
    -
    2940  }
    -
    2941  SECTION( "repetition of qubits" ) {
    -
    2942 
    -
    2943  qubits[GENERATE(1,2)] = qubits[0];
    -
    2944  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("The qubits must be unique") );
    -
    2945  }
    -
    2946  SECTION( "qubit indices" ) {
    -
    2947 
    -
    2948  int inv = GENERATE( -1, NUM_QUBITS );
    -
    2949  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    -
    2950  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid qubit index") );
    -
    2951  }
    -
    2952  SECTION( "number of terms" ) {
    -
    2953 
    -
    2954  int numTerms = GENERATE( -1, 0 );
    -
    2955  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms), Contains("Invalid number of terms in the phase function") );
    -
    2956  }
    -
    2957  SECTION( "bit encoding name" ) {
    -
    2958 
    -
    2959  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    -
    2960  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, enc, NULL, NULL, 1), Contains("Invalid bit encoding") );
    -
    2961  }
    -
    2962  SECTION( "two's complement register" ) {
    -
    2963 
    -
    2964  numQubits = 1;
    -
    2965  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    -
    2966  }
    -
    2967  SECTION( "fractional exponent" ) {
    -
    2968 
    -
    2969  int numTerms = 3;
    -
    2970  qreal coeffs[] = {0,0,0};
    -
    2971  qreal expos[] = {1,2,3};
    -
    2972  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    -
    2973 
    -
    2974  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    -
    2975  }
    -
    2976  SECTION( "negative exponent" ) {
    -
    2977 
    -
    2978  int numTerms = 3;
    -
    2979  qreal coeffs[] = {0,0,0};
    -
    2980  qreal expos[] = {1,2,3};
    -
    2981  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2, -1.5 );
    -
    2982 
    -
    2983  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    -
    2984 
    -
    2985  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    -
    2986  }
    -
    2987  }
    -
    2988  CLEANUP_TEST( quregVec, quregMatr );
    -
    2989 }
    -
    2990 
    -
    2991 
    -
    2992 
    -
    2997 TEST_CASE( "applyPhaseFuncOverrides", "[operators]" ) {
    -
    2998 
    -
    2999  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    3000 
    -
    3001  SECTION( "correctness" ) {
    -
    3002 
    -
    3003  // try every kind of binary encodings
    -
    3004  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    -
    3005 
    -
    3006  // try every sub-register size
    -
    3007  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    -
    3008 
    -
    3009  // force at least 2 qubits in two's compement though
    -
    3010  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    -
    3011  numQubits++;
    +
    2883  // force at least 2 qubits in two's compement though
    +
    2884  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    +
    2885  numQubits++;
    +
    2886 
    +
    2887  // try every possible sub-register
    +
    2888  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    +
    2889 
    +
    2890  // choose a random number of terms in the phase function
    +
    2891  int numTerms = getRandomInt(1, 5);
    +
    2892 
    +
    2893  // populate the phase function with random but POSITIVE-power terms,
    +
    2894  // and in two's complement mode, strictly integer powers
    +
    2895  qreal coeffs[numTerms];
    +
    2896  qreal expons[numTerms];
    +
    2897  for (int t=0; t<numTerms; t++) {
    +
    2898  coeffs[t] = getRandomReal(-10,10);
    +
    2899  if (encoding == TWOS_COMPLEMENT)
    +
    2900  expons[t] = getRandomInt(0, 3+1); // repetition of power is ok
    +
    2901  else
    +
    2902  expons[t] = getRandomReal(0, 3);
    +
    2903  }
    +
    2904 
    +
    2905  // build a reference diagonal matrix, on the reduced Hilbert space
    +
    2906  QMatrix matr = getZeroMatrix( 1 << numQubits );
    +
    2907  for (size_t i=0; i<matr.size(); i++) {
    +
    2908 
    +
    2909  long long int ind = 0;
    +
    2910  if (encoding == UNSIGNED)
    +
    2911  ind = i;
    +
    2912  if (encoding == TWOS_COMPLEMENT)
    +
    2913  ind = getTwosComplement(i, numQubits);
    +
    2914 
    +
    2915  qreal phase = 0;
    +
    2916  for (int t=0; t<numTerms; t++)
    +
    2917  phase += coeffs[t] * pow(ind, expons[t]);
    +
    2918 
    +
    2919  matr[i][i] = expI(phase);
    +
    2920  }
    +
    2921 
    +
    2922  SECTION( "state-vector" ) {
    +
    2923 
    +
    2924  applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms);
    +
    2925  applyReferenceOp(refVec, qubits, numQubits, matr);
    +
    2926  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    +
    2927  }
    +
    2928  SECTION( "density-matrix" ) {
    +
    2929 
    +
    2930  applyPhaseFunc(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms);
    +
    2931  applyReferenceOp(refMatr, qubits, numQubits, matr);
    +
    2932  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    +
    2933  }
    +
    2934  }
    +
    2935  SECTION( "input validation" ) {
    +
    2936 
    +
    2937  int numQubits = 3;
    +
    2938  int qubits[] = {0,1,2};
    +
    2939 
    +
    2940  SECTION( "number of qubits" ) {
    +
    2941 
    +
    2942  numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    +
    2943  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid number of qubits") );
    +
    2944  }
    +
    2945  SECTION( "repetition of qubits" ) {
    +
    2946 
    +
    2947  qubits[GENERATE(1,2)] = qubits[0];
    +
    2948  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("The qubits must be unique") );
    +
    2949  }
    +
    2950  SECTION( "qubit indices" ) {
    +
    2951 
    +
    2952  int inv = GENERATE( -1, NUM_QUBITS );
    +
    2953  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    +
    2954  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), Contains("Invalid qubit index") );
    +
    2955  }
    +
    2956  SECTION( "number of terms" ) {
    +
    2957 
    +
    2958  int numTerms = GENERATE( -1, 0 );
    +
    2959  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms), Contains("Invalid number of terms in the phase function") );
    +
    2960  }
    +
    2961  SECTION( "bit encoding name" ) {
    +
    2962 
    +
    2963  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    +
    2964  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, enc, NULL, NULL, 1), Contains("Invalid bit encoding") );
    +
    2965  }
    +
    2966  SECTION( "two's complement register" ) {
    +
    2967 
    +
    2968  numQubits = 1;
    +
    2969  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    +
    2970  }
    +
    2971  SECTION( "fractional exponent" ) {
    +
    2972 
    +
    2973  int numTerms = 3;
    +
    2974  qreal coeffs[] = {0,0,0};
    +
    2975  qreal expos[] = {1,2,3};
    +
    2976  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    +
    2977 
    +
    2978  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    +
    2979  }
    +
    2980  SECTION( "negative exponent" ) {
    +
    2981 
    +
    2982  int numTerms = 3;
    +
    2983  qreal coeffs[] = {0,0,0};
    +
    2984  qreal expos[] = {1,2,3};
    +
    2985  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2, -1.5 );
    +
    2986 
    +
    2987  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    +
    2988 
    +
    2989  REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    +
    2990  }
    +
    2991  }
    +
    2992  CLEANUP_TEST( quregVec, quregMatr );
    +
    2993 }
    +
    2994 
    +
    2995 
    +
    2996 
    +
    3001 TEST_CASE( "applyPhaseFuncOverrides", "[operators]" ) {
    +
    3002 
    +
    3003  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    3004 
    +
    3005  SECTION( "correctness" ) {
    +
    3006 
    +
    3007  // try every kind of binary encodings
    +
    3008  enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
    +
    3009 
    +
    3010  // try every sub-register size
    +
    3011  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    3012 
    -
    3013  // try every possible sub-register
    -
    3014  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    -
    3015 
    -
    3016  // choose a random number of terms in the phase function
    -
    3017  int numTerms = getRandomInt(1, 21);
    -
    3018 
    -
    3019  // populate the phase function with random powers.
    -
    3020  // this includes negative powers, so we must always override 0.
    -
    3021  // in two's complement, we must use only integer powers
    -
    3022  qreal coeffs[numTerms];
    -
    3023  qreal expons[numTerms];
    -
    3024  for (int t=0; t<numTerms; t++) {
    -
    3025  coeffs[t] = getRandomReal(-10,10);
    -
    3026  if (encoding == TWOS_COMPLEMENT)
    -
    3027  expons[t] = getRandomInt(-3, 3+1); // note we COULD do getRandomReal(), and override all negatives
    -
    3028  else
    -
    3029  expons[t] = getRandomReal(-3, 3);
    -
    3030  }
    -
    3031 
    -
    3032  // choose a random number of overrides (even overriding every amplitude)
    -
    3033  int numOverrides = getRandomInt(1, (1<<numQubits) + 1);
    -
    3034 
    -
    3035  // randomise each override index (uniqueness isn't checked)
    -
    3036  long long int overrideInds[numOverrides];
    -
    3037  overrideInds[0] = 0LL;
    -
    3038  for (int i=1; i<numOverrides; i++)
    -
    3039  if (encoding == UNSIGNED)
    -
    3040  overrideInds[i] = getRandomInt(0, 1<<numQubits);
    -
    3041  else if (encoding == TWOS_COMPLEMENT)
    -
    3042  overrideInds[i] = getRandomInt(-(1<<(numQubits-1)), (1<<(numQubits-1))-1);
    -
    3043 
    -
    3044  // override to a random phase
    -
    3045  qreal overridePhases[numOverrides];
    -
    3046  for (int i=0; i<numOverrides; i++)
    -
    3047  overridePhases[i] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    -
    3048 
    -
    3049  // build a reference diagonal matrix, on the reduced Hilbert space
    -
    3050  QMatrix matr = getZeroMatrix( 1 << numQubits );
    -
    3051  for (size_t i=0; i<matr.size(); i++) {
    +
    3013  // force at least 2 qubits in two's compement though
    +
    3014  if (encoding == TWOS_COMPLEMENT && numQubits == 1)
    +
    3015  numQubits++;
    +
    3016 
    +
    3017  // try every possible sub-register
    +
    3018  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    +
    3019 
    +
    3020  // choose a random number of terms in the phase function
    +
    3021  int numTerms = getRandomInt(1, 21);
    +
    3022 
    +
    3023  // populate the phase function with random powers.
    +
    3024  // this includes negative powers, so we must always override 0.
    +
    3025  // in two's complement, we must use only integer powers
    +
    3026  qreal coeffs[numTerms];
    +
    3027  qreal expons[numTerms];
    +
    3028  for (int t=0; t<numTerms; t++) {
    +
    3029  coeffs[t] = getRandomReal(-10,10);
    +
    3030  if (encoding == TWOS_COMPLEMENT)
    +
    3031  expons[t] = getRandomInt(-3, 3+1); // note we COULD do getRandomReal(), and override all negatives
    +
    3032  else
    +
    3033  expons[t] = getRandomReal(-3, 3);
    +
    3034  }
    +
    3035 
    +
    3036  // choose a random number of overrides (even overriding every amplitude)
    +
    3037  int numOverrides = getRandomInt(1, (1<<numQubits) + 1);
    +
    3038 
    +
    3039  // randomise each override index (uniqueness isn't checked)
    +
    3040  long long int overrideInds[numOverrides];
    +
    3041  overrideInds[0] = 0LL;
    +
    3042  for (int i=1; i<numOverrides; i++)
    +
    3043  if (encoding == UNSIGNED)
    +
    3044  overrideInds[i] = getRandomInt(0, 1<<numQubits);
    +
    3045  else if (encoding == TWOS_COMPLEMENT)
    +
    3046  overrideInds[i] = getRandomInt(-(1<<(numQubits-1)), (1<<(numQubits-1))-1);
    +
    3047 
    +
    3048  // override to a random phase
    +
    3049  qreal overridePhases[numOverrides];
    +
    3050  for (int i=0; i<numOverrides; i++)
    +
    3051  overridePhases[i] = getRandomReal(-4, 4); // periodic in [-pi, pi]
    3052 
    -
    3053  long long int ind = 0;
    -
    3054  if (encoding == UNSIGNED)
    -
    3055  ind = i;
    -
    3056  if (encoding == TWOS_COMPLEMENT)
    -
    3057  ind = getTwosComplement(i, numQubits);
    -
    3058 
    -
    3059  // reference diagonal matrix incorporates overriden phases
    -
    3060  qreal phase;
    -
    3061  bool overriden = false;
    -
    3062  for (int v=0; v<numOverrides; v++) {
    -
    3063  if (ind == overrideInds[v]) {
    -
    3064  phase = overridePhases[v];
    -
    3065  overriden = true;
    -
    3066  break;
    -
    3067  }
    -
    3068  }
    -
    3069 
    -
    3070  if (!overriden) {
    -
    3071  phase = 0;
    -
    3072  for (int t=0; t<numTerms; t++)
    -
    3073  phase += coeffs[t] * pow(ind, expons[t]);
    -
    3074  }
    -
    3075 
    -
    3076  matr[i][i] = expI(phase);
    -
    3077  }
    -
    3078 
    -
    3079  SECTION( "state-vector" ) {
    -
    3080 
    -
    3081  applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    -
    3082  applyReferenceOp(refVec, qubits, numQubits, matr);
    -
    3083  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    -
    3084  }
    -
    3085  SECTION( "density-matrix" ) {
    -
    3086 
    -
    3087  applyPhaseFuncOverrides(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    -
    3088  applyReferenceOp(refMatr, qubits, numQubits, matr);
    -
    3089  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    -
    3090  }
    -
    3091  }
    -
    3092  SECTION( "input validation" ) {
    -
    3093 
    -
    3094  int numQubits = 3;
    -
    3095  int qubits[] = {0,1,2};
    -
    3096 
    -
    3097  SECTION( "number of qubits" ) {
    -
    3098 
    -
    3099  int numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    -
    3100  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid number of qubits") );
    -
    3101  }
    -
    3102  SECTION( "repetition qubits" ) {
    -
    3103 
    -
    3104  qubits[GENERATE(1,2)] = qubits[0];
    -
    3105  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("The qubits must be unique") );
    -
    3106  }
    -
    3107  SECTION( "qubit indices" ) {
    -
    3108 
    -
    3109  int inv = GENERATE( -1, NUM_QUBITS );
    -
    3110  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    -
    3111  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid qubit index") );
    -
    3112  }
    -
    3113  SECTION( "number of terms" ) {
    -
    3114 
    -
    3115  int numTerms = GENERATE( -1, 0 );
    -
    3116  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms, NULL, NULL, 0), Contains("Invalid number of terms in the phase function") );
    -
    3117  }
    -
    3118  SECTION( "bit encoding name" ) {
    -
    3119 
    -
    3120  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    -
    3121  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, enc, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid bit encoding") );
    -
    3122  }
    -
    3123  SECTION( "two's complement register" ) {
    -
    3124 
    -
    3125  numQubits = 1;
    -
    3126  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1, NULL, NULL, 0), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    -
    3127  }
    -
    3128  SECTION( "number of overrides" ) {
    -
    3129 
    -
    3130  qreal dummyTerms[] = {0};
    -
    3131 
    -
    3132  int numOverrides = GENERATE_COPY( -1, 1 + (1<<numQubits) );
    -
    3133  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, dummyTerms, dummyTerms, 1, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides") );
    -
    3134  }
    -
    3135  SECTION( "override indices" ) {
    -
    3136 
    -
    3137  int numOverrides = 3;
    -
    3138  long long int overrideInds[] = {0,1,2};
    -
    3139  qreal overridePhases[] = {.1,.1,.1};
    -
    3140  qreal dummyTerms[] = {0};
    -
    3141 
    -
    3142  enum bitEncoding encoding = UNSIGNED;
    -
    3143  overrideInds[GENERATE(0,1,2)] = GENERATE_COPY( -1, (1<<numQubits) );
    -
    3144  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    3053  // build a reference diagonal matrix, on the reduced Hilbert space
    +
    3054  QMatrix matr = getZeroMatrix( 1 << numQubits );
    +
    3055  for (size_t i=0; i<matr.size(); i++) {
    +
    3056 
    +
    3057  long long int ind = 0;
    +
    3058  if (encoding == UNSIGNED)
    +
    3059  ind = i;
    +
    3060  if (encoding == TWOS_COMPLEMENT)
    +
    3061  ind = getTwosComplement(i, numQubits);
    +
    3062 
    +
    3063  // reference diagonal matrix incorporates overriden phases
    +
    3064  qreal phase;
    +
    3065  bool overriden = false;
    +
    3066  for (int v=0; v<numOverrides; v++) {
    +
    3067  if (ind == overrideInds[v]) {
    +
    3068  phase = overridePhases[v];
    +
    3069  overriden = true;
    +
    3070  break;
    +
    3071  }
    +
    3072  }
    +
    3073 
    +
    3074  if (!overriden) {
    +
    3075  phase = 0;
    +
    3076  for (int t=0; t<numTerms; t++)
    +
    3077  phase += coeffs[t] * pow(ind, expons[t]);
    +
    3078  }
    +
    3079 
    +
    3080  matr[i][i] = expI(phase);
    +
    3081  }
    +
    3082 
    +
    3083  SECTION( "state-vector" ) {
    +
    3084 
    +
    3085  applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    +
    3086  applyReferenceOp(refVec, qubits, numQubits, matr);
    +
    3087  REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
    +
    3088  }
    +
    3089  SECTION( "density-matrix" ) {
    +
    3090 
    +
    3091  applyPhaseFuncOverrides(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
    +
    3092  applyReferenceOp(refMatr, qubits, numQubits, matr);
    +
    3093  REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
    +
    3094  }
    +
    3095  }
    +
    3096  SECTION( "input validation" ) {
    +
    3097 
    +
    3098  int numQubits = 3;
    +
    3099  int qubits[] = {0,1,2};
    +
    3100 
    +
    3101  SECTION( "number of qubits" ) {
    +
    3102 
    +
    3103  int numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
    +
    3104  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid number of qubits") );
    +
    3105  }
    +
    3106  SECTION( "repetition qubits" ) {
    +
    3107 
    +
    3108  qubits[GENERATE(1,2)] = qubits[0];
    +
    3109  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("The qubits must be unique") );
    +
    3110  }
    +
    3111  SECTION( "qubit indices" ) {
    +
    3112 
    +
    3113  int inv = GENERATE( -1, NUM_QUBITS );
    +
    3114  qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
    +
    3115  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid qubit index") );
    +
    3116  }
    +
    3117  SECTION( "number of terms" ) {
    +
    3118 
    +
    3119  int numTerms = GENERATE( -1, 0 );
    +
    3120  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms, NULL, NULL, 0), Contains("Invalid number of terms in the phase function") );
    +
    3121  }
    +
    3122  SECTION( "bit encoding name" ) {
    +
    3123 
    +
    3124  enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
    +
    3125  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, enc, NULL, NULL, 1, NULL, NULL, 0), Contains("Invalid bit encoding") );
    +
    3126  }
    +
    3127  SECTION( "two's complement register" ) {
    +
    3128 
    +
    3129  numQubits = 1;
    +
    3130  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1, NULL, NULL, 0), Contains("too few qubits to employ TWOS_COMPLEMENT") );
    +
    3131  }
    +
    3132  SECTION( "number of overrides" ) {
    +
    3133 
    +
    3134  qreal dummyTerms[] = {0};
    +
    3135 
    +
    3136  int numOverrides = GENERATE_COPY( -1, 1 + (1<<numQubits) );
    +
    3137  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, dummyTerms, dummyTerms, 1, NULL, NULL, numOverrides), Contains("Invalid number of phase function overrides") );
    +
    3138  }
    +
    3139  SECTION( "override indices" ) {
    +
    3140 
    +
    3141  int numOverrides = 3;
    +
    3142  long long int overrideInds[] = {0,1,2};
    +
    3143  qreal overridePhases[] = {.1,.1,.1};
    +
    3144  qreal dummyTerms[] = {0};
    3145 
    -
    3146  encoding = TWOS_COMPLEMENT;
    -
    3147  long long int newInds[] = {0,1,2};
    -
    3148  int minInd = -(1<<(numQubits-1));
    -
    3149  int maxInd = (1<<(numQubits-1)) -1;
    -
    3150  newInds[GENERATE(0,1,2)] = GENERATE_COPY( minInd-1, maxInd+1 );
    -
    3151  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, newInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    -
    3152  }
    -
    3153  SECTION( "fractional exponent" ) {
    -
    3154 
    -
    3155  int numTerms = 3;
    -
    3156  qreal coeffs[] = {0,0,0};
    -
    3157  qreal expos[] = {1,2,3};
    +
    3146  enum bitEncoding encoding = UNSIGNED;
    +
    3147  overrideInds[GENERATE(0,1,2)] = GENERATE_COPY( -1, (1<<numQubits) );
    +
    3148  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, overrideInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the UNSIGNED encoding") );
    +
    3149 
    +
    3150  encoding = TWOS_COMPLEMENT;
    +
    3151  long long int newInds[] = {0,1,2};
    +
    3152  int minInd = -(1<<(numQubits-1));
    +
    3153  int maxInd = (1<<(numQubits-1)) -1;
    +
    3154  newInds[GENERATE(0,1,2)] = GENERATE_COPY( minInd-1, maxInd+1 );
    +
    3155  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, newInds, overridePhases, numOverrides), Contains("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
    +
    3156  }
    +
    3157  SECTION( "fractional exponent" ) {
    3158 
    -
    3159  // make one exponent fractional, thereby requiring negative overrides
    -
    3160  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    -
    3161 
    -
    3162  // catch when no negative indices are overridden
    -
    3163  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, NULL, NULL, 0), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    -
    3164 
    -
    3165  int numNegs = 1 << (numQubits-1);
    -
    3166  long long int overrideInds[numNegs];
    -
    3167  qreal overridePhases[numNegs];
    -
    3168  for (int i=0; i<numNegs; i++) {
    -
    3169  overrideInds[i] = -(i+1);
    -
    3170  overridePhases[i] = 0;
    -
    3171  }
    -
    3172 
    -
    3173  // ensure no throw when all are overriden
    -
    3174  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs) );
    -
    3175 
    -
    3176  // catch when at least one isn't overriden
    -
    3177  overrideInds[GENERATE_COPY( range(0,numNegs) )] = 0; // override a non-negative
    -
    3178  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    -
    3179  }
    -
    3180  SECTION( "negative exponent" ) {
    -
    3181 
    -
    3182  int numTerms = 3;
    -
    3183  qreal coeffs[] = {0,0,0};
    -
    3184  qreal expos[] = {1,2,3};
    -
    3185  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2 );
    -
    3186 
    -
    3187  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    -
    3188 
    -
    3189  // test both when giving no overrides, and giving all non-zero overrides
    -
    3190  int numOverrides = GENERATE( 0, 3 );
    -
    3191  long long int overrideInds[] = {1,2,3};
    -
    3192  qreal overridePhases[] = {0,0,0};
    -
    3193  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    -
    3194 
    -
    3195  // but ensure that when the zero IS overriden (anywhere), there's no error
    -
    3196  numOverrides = 3;
    -
    3197  overrideInds[GENERATE_COPY(range(0,numOverrides))] = 0;
    -
    3198  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides) );
    -
    3199  }
    -
    3200  }
    -
    3201  CLEANUP_TEST( quregVec, quregMatr );
    -
    3202 }
    -
    3203 
    -
    3204 
    -
    3205 
    -
    3210 TEST_CASE( "applyQFT", "[operators]" ) {
    -
    3211 
    -
    3212  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    -
    3213 
    -
    3214  SECTION( "correctness" ) {
    -
    3215 
    -
    3216  // try every sub-register size
    -
    3217  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    -
    3218 
    -
    3219  // try every possible sub-register
    -
    3220  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    -
    3221 
    -
    3222  SECTION( "state-vector" ) {
    -
    3223 
    -
    3224  SECTION( "normalised" ) {
    -
    3225 
    - -
    3227  toQureg(quregVec, refVec);
    -
    3228 
    -
    3229  applyQFT(quregVec, qubits, numQubits);
    -
    3230  refVec = getDFT(refVec, qubits, numQubits);
    -
    3231 
    -
    3232  REQUIRE( areEqual(quregVec, refVec) );
    -
    3233  }
    -
    3234  SECTION( "unnormalised" ) {
    -
    3235 
    -
    3236  QVector refVec = getRandomQVector(1 << NUM_QUBITS);
    -
    3237  toQureg(quregVec, refVec);
    -
    3238 
    -
    3239  applyQFT(quregVec, qubits, numQubits);
    -
    3240  refVec = getDFT(refVec, qubits, numQubits);
    +
    3159  int numTerms = 3;
    +
    3160  qreal coeffs[] = {0,0,0};
    +
    3161  qreal expos[] = {1,2,3};
    +
    3162 
    +
    3163  // make one exponent fractional, thereby requiring negative overrides
    +
    3164  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
    +
    3165 
    +
    3166  // catch when no negative indices are overridden
    +
    3167  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, NULL, NULL, 0), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    +
    3168 
    +
    3169  int numNegs = 1 << (numQubits-1);
    +
    3170  long long int overrideInds[numNegs];
    +
    3171  qreal overridePhases[numNegs];
    +
    3172  for (int i=0; i<numNegs; i++) {
    +
    3173  overrideInds[i] = -(i+1);
    +
    3174  overridePhases[i] = 0;
    +
    3175  }
    +
    3176 
    +
    3177  // ensure no throw when all are overriden
    +
    3178  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs) );
    +
    3179 
    +
    3180  // catch when at least one isn't overriden
    +
    3181  overrideInds[GENERATE_COPY( range(0,numNegs) )] = 0; // override a non-negative
    +
    3182  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs), Contains("fractional exponent") && Contains("TWOS_COMPLEMENT") && Contains("negative indices were not overriden") );
    +
    3183  }
    +
    3184  SECTION( "negative exponent" ) {
    +
    3185 
    +
    3186  int numTerms = 3;
    +
    3187  qreal coeffs[] = {0,0,0};
    +
    3188  qreal expos[] = {1,2,3};
    +
    3189  expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2 );
    +
    3190 
    +
    3191  enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
    +
    3192 
    +
    3193  // test both when giving no overrides, and giving all non-zero overrides
    +
    3194  int numOverrides = GENERATE( 0, 3 );
    +
    3195  long long int overrideInds[] = {1,2,3};
    +
    3196  qreal overridePhases[] = {0,0,0};
    +
    3197  REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides), Contains("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
    +
    3198 
    +
    3199  // but ensure that when the zero IS overriden (anywhere), there's no error
    +
    3200  numOverrides = 3;
    +
    3201  overrideInds[GENERATE_COPY(range(0,numOverrides))] = 0;
    +
    3202  REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides) );
    +
    3203  }
    +
    3204  }
    +
    3205  CLEANUP_TEST( quregVec, quregMatr );
    +
    3206 }
    +
    3207 
    +
    3208 
    +
    3209 
    +
    3214 TEST_CASE( "applyProjector", "[operators]" ) {
    +
    3215 
    + + +
    3218 
    +
    3219  SECTION( "correctness" ) {
    +
    3220 
    +
    3221  int qubit = GENERATE( range(0,NUM_QUBITS) );
    +
    3222  int outcome = GENERATE( 0, 1 );
    +
    3223 
    +
    3224  // repeat these random tests 10 times on every qubit, and for both outcomes
    +
    3225  GENERATE( range(0,10) );
    +
    3226 
    +
    3227  SECTION( "state-vector" ) {
    +
    3228 
    +
    3229  SECTION( "normalised" ) {
    +
    3230 
    +
    3231  // use a random L2 state for every qubit & outcome
    + +
    3233  toQureg(vec, vecRef);
    +
    3234 
    +
    3235  // zero non-outcome reference amps
    +
    3236  for (size_t ind=0; ind<vecRef.size(); ind++) {
    +
    3237  int bit = (ind >> qubit) & 1; // target-th bit
    +
    3238  if (bit != outcome)
    +
    3239  vecRef[ind] = 0;
    +
    3240  }
    3241 
    -
    3242  REQUIRE( areEqual(quregVec, refVec) );
    -
    3243  }
    -
    3244  }
    -
    3245  SECTION( "density-matrix" ) {
    -
    3246 
    -
    3247  SECTION( "pure" ) {
    -
    3248 
    -
    3249  /* a pure density matrix should be mapped to a pure state
    -
    3250  * corresponding to the state-vector DFT
    -
    3251  */
    -
    3252 
    -
    3253  refVec = getRandomStateVector(NUM_QUBITS);
    -
    3254  refMatr = getPureDensityMatrix(refVec);
    -
    3255  toQureg(quregMatr, refMatr);
    -
    3256 
    -
    3257  applyQFT(quregMatr, qubits, numQubits);
    -
    3258  refVec = getDFT(refVec, qubits, numQubits);
    -
    3259  refMatr = getPureDensityMatrix(refVec);
    -
    3260 
    -
    3261  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    3262  }
    -
    3263  SECTION( "mixed" ) {
    -
    3264 
    -
    3265  /* a mixed density matrix, conceptualised as a mixture of orthogonal
    -
    3266  * state-vectors, should be mapped to an equally weighted mixture
    -
    3267  * of DFTs of each state-vector (because QFT is unitary and hence
    -
    3268  * maintains state orthogonality)
    -
    3269  */
    -
    3270 
    -
    3271  int numStates = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    -
    3272  std::vector<QVector> states = getRandomOrthonormalVectors(NUM_QUBITS, numStates);
    -
    3273  std::vector<qreal> probs = getRandomProbabilities(numStates);
    -
    3274 
    -
    3275  // set qureg to random mixture of state-vectors
    -
    3276  refMatr = getMixedDensityMatrix(probs, states);
    -
    3277  toQureg(quregMatr, refMatr);
    -
    3278 
    -
    3279  // apply QFT to mixture
    -
    3280  applyQFT(quregMatr, qubits, numQubits);
    +
    3242  applyProjector(vec, qubit, outcome);
    +
    3243  REQUIRE( areEqual(vec, vecRef) );
    +
    3244  }
    +
    3245  SECTION( "unnormalised" ) {
    +
    3246 
    +
    3247  // use a random non-physical state for every qubit & outcome
    +
    3248  QVector vecRef = getRandomQVector(1 << NUM_QUBITS);
    +
    3249  toQureg(vec, vecRef);
    +
    3250 
    +
    3251  // zero non-outcome reference amps
    +
    3252  for (size_t ind=0; ind<vecRef.size(); ind++) {
    +
    3253  int bit = (ind >> qubit) & 1; // target-th bit
    +
    3254  if (bit != outcome)
    +
    3255  vecRef[ind] = 0;
    +
    3256  }
    +
    3257 
    +
    3258  applyProjector(vec, qubit, outcome);
    +
    3259  REQUIRE( areEqual(vec, vecRef) );
    +
    3260  }
    +
    3261  }
    +
    3262  SECTION( "density-matrix" ) {
    +
    3263 
    +
    3264  SECTION( "pure" ) {
    +
    3265 
    + +
    3267  QMatrix matRef = getPureDensityMatrix(vecRef);
    +
    3268 
    +
    3269  toQureg(mat, matRef);
    +
    3270  applyProjector(mat, qubit, outcome);
    +
    3271 
    +
    3272  // zero any amplitudes that aren't |outcome><outcome|
    +
    3273  for (size_t r=0; r<matRef.size(); r++) {
    +
    3274  for (size_t c=0; c<matRef.size(); c++) {
    +
    3275  int ketBit = (c >> qubit) & 1;
    +
    3276  int braBit = (r >> qubit) & 1;
    +
    3277  if (!(ketBit == outcome && braBit == outcome))
    +
    3278  matRef[r][c] = 0;
    +
    3279  }
    +
    3280  }
    3281 
    -
    3282  // compute dft of mixture, via dft of each state
    -
    3283  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    -
    3284  for (int i=0; i<numStates; i++) {
    -
    3285  QVector dft = getDFT(states[i], qubits, numQubits);
    -
    3286  refMatr += probs[i] * getPureDensityMatrix(dft);
    -
    3287  }
    -
    3288 
    -
    3289  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    3290  }
    -
    3291  SECTION( "unnormalised" ) {
    -
    3292 
    -
    3293  /* repeat method above, except that we use unnormalised vectors,
    -
    3294  * and mix them with arbitrary complex numbers instead of probabilities,
    -
    3295  * yielding an unnormalised density matrix
    -
    3296  */
    -
    3297 
    -
    3298  int numVecs = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    -
    3299  std::vector<QVector> vecs;
    -
    3300  std::vector<qcomp> coeffs;
    -
    3301  for (int i=0; i<numVecs; i++) {
    -
    3302  vecs.push_back(getRandomQVector(1 << NUM_QUBITS));
    -
    3303  coeffs.push_back(getRandomComplex());
    -
    3304  }
    -
    3305 
    -
    3306  // produce unnormalised matrix via random complex sum of random unnormalised vectors
    -
    3307  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    -
    3308  for (int i=0; i<numVecs; i++)
    -
    3309  refMatr += coeffs[i] * getPureDensityMatrix(vecs[i]);
    -
    3310 
    -
    3311  toQureg(quregMatr, refMatr);
    -
    3312  applyQFT(quregMatr, qubits, numQubits);
    -
    3313 
    -
    3314  // compute target matrix via dft of each unnormalised vector
    -
    3315  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    -
    3316  for (int i=0; i<numVecs; i++) {
    -
    3317  QVector dft = getDFT(vecs[i], qubits, numQubits);
    -
    3318  refMatr += coeffs[i] * getPureDensityMatrix(dft);
    -
    3319  }
    -
    3320 
    -
    3321  REQUIRE( areEqual(quregMatr, refMatr) );
    -
    3322  }
    -
    3323  }
    -
    3324  }
    -
    3325  SECTION( "input validation" ) {
    -
    3326 
    -
    3327  SECTION( "number of targets" ) {
    -
    3328 
    -
    3329  // there cannot be more targets than qubits in register
    -
    3330  int numQubits = GENERATE( -1, 0, NUM_QUBITS+1 );
    -
    3331  int qubits[NUM_QUBITS+1];
    -
    3332 
    -
    3333  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid number of target"));
    -
    3334  }
    -
    3335  SECTION( "repetition in targets" ) {
    -
    3336 
    -
    3337  int numQubits = 3;
    -
    3338  int qubits[] = {1,2,2};
    -
    3339 
    -
    3340  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("target") && Contains("unique"));
    -
    3341  }
    -
    3342  SECTION( "qubit indices" ) {
    -
    3343 
    -
    3344  int numQubits = 3;
    -
    3345  int qubits[] = {1,2,3};
    -
    3346 
    -
    3347  int inv = GENERATE( -1, NUM_QUBITS );
    -
    3348  qubits[GENERATE_COPY( range(0,numQubits) )] = inv; // make invalid target
    -
    3349  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid target") );
    -
    3350  }
    -
    3351  }
    -
    3352  CLEANUP_TEST( quregVec, quregMatr );
    -
    3353 }
    -
    3354 
    -
    3355 
    -
    3356 
    -
    3361 TEST_CASE( "applyTrotterCircuit", "[operators]" ) {
    -
    3362 
    - - -
    3365  initDebugState(vec);
    -
    3366  initDebugState(mat);
    -
    3367 
    -
    3368  Qureg vecRef = createCloneQureg(vec, QUEST_ENV);
    -
    3369  Qureg matRef = createCloneQureg(mat, QUEST_ENV);
    -
    3370 
    -
    3371  SECTION( "correctness" ) {
    -
    3372 
    -
    3373  SECTION( "one term" ) {
    -
    3374 
    -
    3375  // a Hamiltonian with one term has an exact (trivial) Trotterisation
    - -
    3377 
    -
    3378  // H = coeff X Y Z (on qubits 0,1,2)
    -
    3379  qreal coeff = getRandomReal(-5, 5);
    -
    3380  int numTargs = 3;
    -
    3381  int targs[] = {0, 1, 2};
    -
    3382  pauliOpType codes[] = {PAULI_X, PAULI_Y, PAULI_Z};
    -
    3383  hamil.termCoeffs[0] = coeff;
    -
    3384  for (int i=0; i<numTargs; i++)
    -
    3385  hamil.pauliCodes[targs[i]] = codes[i];
    -
    3386 
    -
    3387  // time can be negative
    -
    3388  qreal time = getRandomReal(-2,2);
    -
    3389 
    -
    3390  // by commutation, all reps & orders yield the same total unitary
    -
    3391  int reps = GENERATE( range(1,5) );
    -
    3392 
    -
    3393  // applyTrotter(t, 1, 1) = exp(-i t coeff paulis)
    -
    3394  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    -
    3395 
    -
    3396  SECTION( "state-vector" ) {
    -
    3397 
    -
    3398  int order = GENERATE( 1, 2, 4 );
    +
    3282  REQUIRE( areEqual(mat, matRef) );
    +
    3283  }
    +
    3284  SECTION( "mixed" ) {
    +
    3285 
    + +
    3287 
    +
    3288  toQureg(mat, matRef);
    +
    3289  applyProjector(mat, qubit, outcome);
    +
    3290 
    +
    3291  // zero any amplitudes that aren't |outcome><outcome|
    +
    3292  for (size_t r=0; r<matRef.size(); r++) {
    +
    3293  for (size_t c=0; c<matRef.size(); c++) {
    +
    3294  int ketBit = (c >> qubit) & 1;
    +
    3295  int braBit = (r >> qubit) & 1;
    +
    3296  if (!(ketBit == outcome && braBit == outcome))
    +
    3297  matRef[r][c] = 0;
    +
    3298  }
    +
    3299  }
    +
    3300 
    +
    3301  REQUIRE( areEqual(mat, matRef) );
    +
    3302  }
    +
    3303  SECTION( "unnormalised" ) {
    +
    3304 
    +
    3305  QMatrix matRef = getRandomQMatrix(1 << NUM_QUBITS);
    +
    3306 
    +
    3307  toQureg(mat, matRef);
    +
    3308  applyProjector(mat, qubit, outcome);
    +
    3309 
    +
    3310  // zero any amplitudes that aren't |outcome><outcome|
    +
    3311  for (size_t r=0; r<matRef.size(); r++) {
    +
    3312  for (size_t c=0; c<matRef.size(); c++) {
    +
    3313  int ketBit = (c >> qubit) & 1;
    +
    3314  int braBit = (r >> qubit) & 1;
    +
    3315  if (!(ketBit == outcome && braBit == outcome))
    +
    3316  matRef[r][c] = 0;
    +
    3317  }
    +
    3318  }
    +
    3319 
    +
    3320  REQUIRE( areEqual(mat, matRef) );
    +
    3321  }
    +
    3322  }
    +
    3323  }
    +
    3324  SECTION( "input validation" ) {
    +
    3325 
    +
    3326  SECTION( "qubit index" ) {
    +
    3327 
    +
    3328  int qubit = GENERATE( -1, NUM_QUBITS );
    +
    3329  int outcome = 0;
    +
    3330  REQUIRE_THROWS_WITH( applyProjector(mat, qubit, outcome), Contains("Invalid target qubit") );
    +
    3331  }
    +
    3332  SECTION( "outcome value" ) {
    +
    3333 
    +
    3334  int qubit = 0;
    +
    3335  int outcome = GENERATE( -1, 2 );
    +
    3336  REQUIRE_THROWS_WITH( applyProjector(mat, qubit, outcome), Contains("Invalid measurement outcome") );
    +
    3337  }
    +
    3338  }
    +
    3339  destroyQureg(vec, QUEST_ENV);
    +
    3340  destroyQureg(mat, QUEST_ENV);
    +
    3341 }
    +
    3342 
    +
    3343 
    +
    3344 
    +
    3349 TEST_CASE( "applyQFT", "[operators]" ) {
    +
    3350 
    +
    3351  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
    +
    3352 
    +
    3353  SECTION( "correctness" ) {
    +
    3354 
    +
    3355  // try every sub-register size
    +
    3356  int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
    +
    3357 
    +
    3358  // try every possible sub-register
    +
    3359  int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
    +
    3360 
    +
    3361  SECTION( "state-vector" ) {
    +
    3362 
    +
    3363  SECTION( "normalised" ) {
    +
    3364 
    + +
    3366  toQureg(quregVec, refVec);
    +
    3367 
    +
    3368  applyQFT(quregVec, qubits, numQubits);
    +
    3369  refVec = getDFT(refVec, qubits, numQubits);
    +
    3370 
    +
    3371  REQUIRE( areEqual(quregVec, refVec) );
    +
    3372  }
    +
    3373  SECTION( "unnormalised" ) {
    +
    3374 
    +
    3375  QVector refVec = getRandomQVector(1 << NUM_QUBITS);
    +
    3376  toQureg(quregVec, refVec);
    +
    3377 
    +
    3378  applyQFT(quregVec, qubits, numQubits);
    +
    3379  refVec = getDFT(refVec, qubits, numQubits);
    +
    3380 
    +
    3381  REQUIRE( areEqual(quregVec, refVec) );
    +
    3382  }
    +
    3383  }
    +
    3384  SECTION( "density-matrix" ) {
    +
    3385 
    +
    3386  SECTION( "pure" ) {
    +
    3387 
    +
    3388  /* a pure density matrix should be mapped to a pure state
    +
    3389  * corresponding to the state-vector DFT
    +
    3390  */
    +
    3391 
    +
    3392  refVec = getRandomStateVector(NUM_QUBITS);
    +
    3393  refMatr = getPureDensityMatrix(refVec);
    +
    3394  toQureg(quregMatr, refMatr);
    +
    3395 
    +
    3396  applyQFT(quregMatr, qubits, numQubits);
    +
    3397  refVec = getDFT(refVec, qubits, numQubits);
    +
    3398  refMatr = getPureDensityMatrix(refVec);
    3399 
    -
    3400  applyTrotterCircuit(vec, hamil, time, order, reps);
    -
    3401  multiRotatePauli(vecRef, targs, codes, numTargs, 2*time*coeff);
    -
    3402  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    -
    3403  }
    -
    3404  SECTION( "density-matrix" ) {
    -
    3405 
    -
    3406  int order = GENERATE( 1, 2 ); // precision bites density-matrices quickly
    -
    3407 
    -
    3408  applyTrotterCircuit(mat, hamil, time, order, reps);
    -
    3409  multiRotatePauli(matRef, targs, codes, numTargs, 2*time*coeff);
    -
    3410  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    -
    3411  }
    -
    3412 
    -
    3413  destroyPauliHamil(hamil);
    -
    3414  }
    -
    3415  SECTION( "commuting terms" ) {
    -
    3416 
    -
    3417  // a Hamiltonian of commuting terms, Trotterises exactly
    - -
    3419 
    -
    3420  // H = c0 X Y I + c1 X I Z (on qubits 0,1,2)
    -
    3421  int targs[] = {0, 1, 2};
    -
    3422  hamil.pauliCodes[0] = PAULI_X;
    -
    3423  hamil.pauliCodes[0 + NUM_QUBITS] = PAULI_X;
    -
    3424  hamil.pauliCodes[1] = PAULI_Y;
    -
    3425  hamil.pauliCodes[1 + NUM_QUBITS] = PAULI_I;
    -
    3426  hamil.pauliCodes[2] = PAULI_I;
    -
    3427  hamil.pauliCodes[2 + NUM_QUBITS] = PAULI_Z;
    -
    3428  for (int i=0; i<hamil.numSumTerms; i++)
    -
    3429  hamil.termCoeffs[i] = getRandomReal(-5,5);
    -
    3430 
    -
    3431  // time can be negative
    -
    3432  qreal time = getRandomReal(-2,2);
    -
    3433 
    -
    3434  // applyTrotter(t, 1, 1) = exp(-i t c0 paulis0) exp(-i t c1 paulis1)
    -
    3435  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    -
    3436 
    -
    3437  SECTION( "state-vector" ) {
    -
    3438 
    -
    3439  int reps = GENERATE( range(1,5) );
    -
    3440  int order = GENERATE( 1, 2, 4 );
    -
    3441 
    -
    3442  applyTrotterCircuit(vec, hamil, time, order, reps);
    -
    3443  multiRotatePauli(vecRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    -
    3444  multiRotatePauli(vecRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    -
    3445  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    -
    3446  }
    -
    3447  SECTION( "density-matrix" ) {
    -
    3448 
    -
    3449  int reps = GENERATE( range(1,5) );
    -
    3450  int order = GENERATE( 1, 2 ); // precision hurts density matrices quickly
    -
    3451 
    -
    3452  applyTrotterCircuit(mat, hamil, time, order, reps);
    -
    3453  multiRotatePauli(matRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    -
    3454  multiRotatePauli(matRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    -
    3455  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    -
    3456  }
    -
    3457 
    -
    3458  destroyPauliHamil(hamil);
    -
    3459  }
    -
    3460  SECTION( "general" ) {
    -
    3461 
    -
    3462  /* We'll consider an analytic time-evolved state, so that we can avoid
    -
    3463  * comparing applyTrotterCircuit to other numerical approximations.
    -
    3464  * We can construct such a state, by using a Hamiltonian with known
    -
    3465  * analytic eigenvalues, and hence a known period. Time evolution of the
    -
    3466  * period will just yield the input state.
    -
    3467  *
    -
    3468  * E.g. H = pi sqrt(2) X Y Z X Y + pi Y Z X Y Z + pi Z X Y Z X
    -
    3469  * has (degenerate) eigenvalues +- 2 pi, so the period
    -
    3470  * of the Hamiltonian is t=1.
    -
    3471  */
    -
    3472 
    -
    3473  // hardcoded 5 qubits here in the Pauli codes
    -
    3474  REQUIRE( NUM_QUBITS == 5 );
    +
    3400  REQUIRE( areEqual(quregMatr, refMatr) );
    +
    3401  }
    +
    3402  SECTION( "mixed" ) {
    +
    3403 
    +
    3404  /* a mixed density matrix, conceptualised as a mixture of orthogonal
    +
    3405  * state-vectors, should be mapped to an equally weighted mixture
    +
    3406  * of DFTs of each state-vector (because QFT is unitary and hence
    +
    3407  * maintains state orthogonality)
    +
    3408  */
    +
    3409 
    +
    3410  int numStates = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    +
    3411  std::vector<QVector> states = getRandomOrthonormalVectors(NUM_QUBITS, numStates);
    +
    3412  std::vector<qreal> probs = getRandomProbabilities(numStates);
    +
    3413 
    +
    3414  // set qureg to random mixture of state-vectors
    +
    3415  refMatr = getMixedDensityMatrix(probs, states);
    +
    3416  toQureg(quregMatr, refMatr);
    +
    3417 
    +
    3418  // apply QFT to mixture
    +
    3419  applyQFT(quregMatr, qubits, numQubits);
    +
    3420 
    +
    3421  // compute dft of mixture, via dft of each state
    +
    3422  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    +
    3423  for (int i=0; i<numStates; i++) {
    +
    3424  QVector dft = getDFT(states[i], qubits, numQubits);
    +
    3425  refMatr += probs[i] * getPureDensityMatrix(dft);
    +
    3426  }
    +
    3427 
    +
    3428  REQUIRE( areEqual(quregMatr, refMatr) );
    +
    3429  }
    +
    3430  SECTION( "unnormalised" ) {
    +
    3431 
    +
    3432  /* repeat method above, except that we use unnormalised vectors,
    +
    3433  * and mix them with arbitrary complex numbers instead of probabilities,
    +
    3434  * yielding an unnormalised density matrix
    +
    3435  */
    +
    3436 
    +
    3437  int numVecs = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
    +
    3438  std::vector<QVector> vecs;
    +
    3439  std::vector<qcomp> coeffs;
    +
    3440  for (int i=0; i<numVecs; i++) {
    +
    3441  vecs.push_back(getRandomQVector(1 << NUM_QUBITS));
    +
    3442  coeffs.push_back(getRandomComplex());
    +
    3443  }
    +
    3444 
    +
    3445  // produce unnormalised matrix via random complex sum of random unnormalised vectors
    +
    3446  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    +
    3447  for (int i=0; i<numVecs; i++)
    +
    3448  refMatr += coeffs[i] * getPureDensityMatrix(vecs[i]);
    +
    3449 
    +
    3450  toQureg(quregMatr, refMatr);
    +
    3451  applyQFT(quregMatr, qubits, numQubits);
    +
    3452 
    +
    3453  // compute target matrix via dft of each unnormalised vector
    +
    3454  refMatr = getZeroMatrix(1 << NUM_QUBITS);
    +
    3455  for (int i=0; i<numVecs; i++) {
    +
    3456  QVector dft = getDFT(vecs[i], qubits, numQubits);
    +
    3457  refMatr += coeffs[i] * getPureDensityMatrix(dft);
    +
    3458  }
    +
    3459 
    +
    3460  REQUIRE( areEqual(quregMatr, refMatr) );
    +
    3461  }
    +
    3462  }
    +
    3463  }
    +
    3464  SECTION( "input validation" ) {
    +
    3465 
    +
    3466  SECTION( "number of targets" ) {
    +
    3467 
    +
    3468  // there cannot be more targets than qubits in register
    +
    3469  int numQubits = GENERATE( -1, 0, NUM_QUBITS+1 );
    +
    3470  int qubits[NUM_QUBITS+1];
    +
    3471 
    +
    3472  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid number of target"));
    +
    3473  }
    +
    3474  SECTION( "repetition in targets" ) {
    3475 
    - -
    3477  qreal coeffs[] = {(qreal) (M_PI * sqrt(2.0)), M_PI, M_PI};
    -
    3478  enum pauliOpType codes[] = {
    - - - -
    3482  initPauliHamil(hamil, coeffs, codes);
    -
    3483 
    -
    3484  // evolving to t=1 should leave the input state unchanged
    -
    3485  qreal time = 1;
    -
    3486 
    -
    3487  // since unnormalised (initDebugState), max fid is 728359.8336
    -
    3488  qreal fidNorm = 728359.8336;
    -
    3489 
    -
    3490  SECTION( "absolute" ) {
    -
    3491 
    -
    3492  // such a high order and reps should yield precise solution
    -
    3493  int order = 4;
    -
    3494  int reps = 20;
    -
    3495  applyTrotterCircuit(vec, hamil, time, 4, 20);
    -
    3496  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    3497 
    -
    3498  REQUIRE( fid == Approx(1).epsilon(1E-8) );
    -
    3499  }
    -
    3500  SECTION( "repetitions scaling" ) {
    -
    3501 
    -
    3502  // exclude order 1; too few reps for monotonic increase of accuracy
    -
    3503  int order = GENERATE( 2, 4, 6 );
    -
    3504 
    -
    3505  // accuracy should increase with increasing repetitions
    -
    3506  int reps[] = {1, 5, 10};
    -
    3507 
    -
    3508  qreal prevFid = 0;
    -
    3509  for (int i=0; i<3; i++) {
    -
    3510  initDebugState(vec);
    -
    3511  applyTrotterCircuit(vec, hamil, time, order, reps[i]);
    -
    3512  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    3513 
    -
    3514  REQUIRE( fid >= prevFid );
    -
    3515  prevFid = fid;
    -
    3516  }
    -
    3517  }
    -
    3518  SECTION( "order scaling" ) {
    -
    3519 
    -
    3520  // exclude order 1; too few reps for monotonic increase of accuracy
    -
    3521  int reps = GENERATE( 5, 10 );
    -
    3522 
    -
    3523  // accuracy should increase with increasing repetitions
    -
    3524  int orders[] = {1, 2, 4, 6};
    +
    3476  int numQubits = 3;
    +
    3477  int qubits[] = {1,2,2};
    +
    3478 
    +
    3479  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("target") && Contains("unique"));
    +
    3480  }
    +
    3481  SECTION( "qubit indices" ) {
    +
    3482 
    +
    3483  int numQubits = 3;
    +
    3484  int qubits[] = {1,2,3};
    +
    3485 
    +
    3486  int inv = GENERATE( -1, NUM_QUBITS );
    +
    3487  qubits[GENERATE_COPY( range(0,numQubits) )] = inv; // make invalid target
    +
    3488  REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), Contains("Invalid target") );
    +
    3489  }
    +
    3490  }
    +
    3491  CLEANUP_TEST( quregVec, quregMatr );
    +
    3492 }
    +
    3493 
    +
    3494 
    +
    3495 
    +
    3500 TEST_CASE( "applyTrotterCircuit", "[operators]" ) {
    +
    3501 
    + + +
    3504  initDebugState(vec);
    +
    3505  initDebugState(mat);
    +
    3506 
    +
    3507  Qureg vecRef = createCloneQureg(vec, QUEST_ENV);
    +
    3508  Qureg matRef = createCloneQureg(mat, QUEST_ENV);
    +
    3509 
    +
    3510  SECTION( "correctness" ) {
    +
    3511 
    +
    3512  SECTION( "one term" ) {
    +
    3513 
    +
    3514  // a Hamiltonian with one term has an exact (trivial) Trotterisation
    + +
    3516 
    +
    3517  // H = coeff X Y Z (on qubits 0,1,2)
    +
    3518  qreal coeff = getRandomReal(-5, 5);
    +
    3519  int numTargs = 3;
    +
    3520  int targs[] = {0, 1, 2};
    +
    3521  pauliOpType codes[] = {PAULI_X, PAULI_Y, PAULI_Z};
    +
    3522  hamil.termCoeffs[0] = coeff;
    +
    3523  for (int i=0; i<numTargs; i++)
    +
    3524  hamil.pauliCodes[targs[i]] = codes[i];
    3525 
    -
    3526  qreal prevFid = 0;
    -
    3527  for (int i=0; i<4; i++) {
    -
    3528  initDebugState(vec);
    -
    3529  applyTrotterCircuit(vec, hamil, time, orders[i], reps);
    -
    3530  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    -
    3531 
    -
    3532  REQUIRE( fid >= prevFid );
    -
    3533  prevFid = fid;
    -
    3534  }
    -
    3535  }
    -
    3536 
    -
    3537  destroyPauliHamil(hamil);
    -
    3538  }
    -
    3539  }
    -
    3540  SECTION( "input validation" ) {
    -
    3541 
    -
    3542  SECTION( "repetitions" ) {
    -
    3543 
    - -
    3545  int reps = GENERATE( -1, 0 );
    -
    3546 
    -
    3547  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, reps), Contains("repetitions must be >=1") );
    -
    3548 
    -
    3549  destroyPauliHamil(hamil);
    -
    3550  }
    -
    3551  SECTION( "order" ) {
    -
    3552 
    - -
    3554  int order = GENERATE( -1, 0, 3, 5, 7 );
    +
    3526  // time can be negative
    +
    3527  qreal time = getRandomReal(-2,2);
    +
    3528 
    +
    3529  // by commutation, all reps & orders yield the same total unitary
    +
    3530  int reps = GENERATE( range(1,5) );
    +
    3531 
    +
    3532  // applyTrotter(t, 1, 1) = exp(-i t coeff paulis)
    +
    3533  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    +
    3534 
    +
    3535  SECTION( "state-vector" ) {
    +
    3536 
    +
    3537  int order = GENERATE( 1, 2, 4 );
    +
    3538 
    +
    3539  applyTrotterCircuit(vec, hamil, time, order, reps);
    +
    3540  multiRotatePauli(vecRef, targs, codes, numTargs, 2*time*coeff);
    +
    3541  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    +
    3542  }
    +
    3543  SECTION( "density-matrix" ) {
    +
    3544 
    +
    3545  int order = GENERATE( 1, 2 ); // precision bites density-matrices quickly
    +
    3546 
    +
    3547  applyTrotterCircuit(mat, hamil, time, order, reps);
    +
    3548  multiRotatePauli(matRef, targs, codes, numTargs, 2*time*coeff);
    +
    3549  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    +
    3550  }
    +
    3551 
    +
    3552  destroyPauliHamil(hamil);
    +
    3553  }
    +
    3554  SECTION( "commuting terms" ) {
    3555 
    -
    3556  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, order, 1), Contains("order must be 1, or an even number") );
    -
    3557 
    -
    3558  destroyPauliHamil(hamil);
    -
    3559  }
    -
    3560  SECTION( "pauli codes" ) {
    -
    3561 
    -
    3562  int numTerms = 3;
    -
    3563  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    -
    3564 
    -
    3565  // make one pauli code wrong
    -
    3566  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    -
    3567  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("Invalid Pauli code") );
    -
    3568 
    -
    3569  destroyPauliHamil(hamil);
    -
    3570  }
    -
    3571  SECTION( "matching hamiltonian qubits" ) {
    +
    3556  // a Hamiltonian of commuting terms, Trotterises exactly
    + +
    3558 
    +
    3559  // H = c0 X Y I + c1 X I Z (on qubits 0,1,2)
    +
    3560  int targs[] = {0, 1, 2};
    +
    3561  hamil.pauliCodes[0] = PAULI_X;
    +
    3562  hamil.pauliCodes[0 + NUM_QUBITS] = PAULI_X;
    +
    3563  hamil.pauliCodes[1] = PAULI_Y;
    +
    3564  hamil.pauliCodes[1 + NUM_QUBITS] = PAULI_I;
    +
    3565  hamil.pauliCodes[2] = PAULI_I;
    +
    3566  hamil.pauliCodes[2 + NUM_QUBITS] = PAULI_Z;
    +
    3567  for (int i=0; i<hamil.numSumTerms; i++)
    +
    3568  hamil.termCoeffs[i] = getRandomReal(-5,5);
    +
    3569 
    +
    3570  // time can be negative
    +
    3571  qreal time = getRandomReal(-2,2);
    3572 
    -
    3573  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    -
    3574 
    -
    3575  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("same number of qubits") );
    -
    3576  REQUIRE_THROWS_WITH( applyTrotterCircuit(mat, hamil, 1, 1, 1), Contains("same number of qubits") );
    -
    3577 
    -
    3578  destroyPauliHamil(hamil);
    -
    3579  }
    -
    3580  }
    -
    3581 
    -
    3582  destroyQureg(vec, QUEST_ENV);
    -
    3583  destroyQureg(mat, QUEST_ENV);
    -
    3584  destroyQureg(vecRef, QUEST_ENV);
    -
    3585  destroyQureg(matRef, QUEST_ENV);
    -
    3586 }
    -
    3587 
    +
    3573  // applyTrotter(t, 1, 1) = exp(-i t c0 paulis0) exp(-i t c1 paulis1)
    +
    3574  // multiRotatePauli(a) = exp(- i a / 2 paulis)
    +
    3575 
    +
    3576  SECTION( "state-vector" ) {
    +
    3577 
    +
    3578  int reps = GENERATE( range(1,5) );
    +
    3579  int order = GENERATE( 1, 2, 4 );
    +
    3580 
    +
    3581  applyTrotterCircuit(vec, hamil, time, order, reps);
    +
    3582  multiRotatePauli(vecRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    +
    3583  multiRotatePauli(vecRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    +
    3584  REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
    +
    3585  }
    +
    3586  SECTION( "density-matrix" ) {
    +
    3587 
    +
    3588  int reps = GENERATE( range(1,5) );
    +
    3589  int order = GENERATE( 1, 2 ); // precision hurts density matrices quickly
    +
    3590 
    +
    3591  applyTrotterCircuit(mat, hamil, time, order, reps);
    +
    3592  multiRotatePauli(matRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
    +
    3593  multiRotatePauli(matRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
    +
    3594  REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
    +
    3595  }
    +
    3596 
    +
    3597  destroyPauliHamil(hamil);
    +
    3598  }
    +
    3599  SECTION( "general" ) {
    +
    3600 
    +
    3601  /* We'll consider an analytic time-evolved state, so that we can avoid
    +
    3602  * comparing applyTrotterCircuit to other numerical approximations.
    +
    3603  * We can construct such a state, by using a Hamiltonian with known
    +
    3604  * analytic eigenvalues, and hence a known period. Time evolution of the
    +
    3605  * period will just yield the input state.
    +
    3606  *
    +
    3607  * E.g. H = pi sqrt(2) X Y Z X Y + pi Y Z X Y Z + pi Z X Y Z X
    +
    3608  * has (degenerate) eigenvalues +- 2 pi, so the period
    +
    3609  * of the Hamiltonian is t=1.
    +
    3610  */
    +
    3611 
    +
    3612  // hardcoded 5 qubits here in the Pauli codes
    +
    3613  REQUIRE( NUM_QUBITS == 5 );
    +
    3614 
    + +
    3616  qreal coeffs[] = {(qreal) (M_PI * sqrt(2.0)), M_PI, M_PI};
    +
    3617  enum pauliOpType codes[] = {
    + + + +
    3621  initPauliHamil(hamil, coeffs, codes);
    +
    3622 
    +
    3623  // evolving to t=1 should leave the input state unchanged
    +
    3624  qreal time = 1;
    +
    3625 
    +
    3626  // since unnormalised (initDebugState), max fid is 728359.8336
    +
    3627  qreal fidNorm = 728359.8336;
    +
    3628 
    +
    3629  SECTION( "absolute" ) {
    +
    3630 
    +
    3631  // such a high order and reps should yield precise solution
    +
    3632  int order = 4;
    +
    3633  int reps = 20;
    +
    3634  applyTrotterCircuit(vec, hamil, time, 4, 20);
    +
    3635  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    +
    3636 
    +
    3637  REQUIRE( fid == Approx(1).epsilon(1E-8) );
    +
    3638  }
    +
    3639  SECTION( "repetitions scaling" ) {
    +
    3640 
    +
    3641  // exclude order 1; too few reps for monotonic increase of accuracy
    +
    3642  int order = GENERATE( 2, 4, 6 );
    +
    3643 
    +
    3644  // accuracy should increase with increasing repetitions
    +
    3645  int reps[] = {1, 5, 10};
    +
    3646 
    +
    3647  qreal prevFid = 0;
    +
    3648  for (int i=0; i<3; i++) {
    +
    3649  initDebugState(vec);
    +
    3650  applyTrotterCircuit(vec, hamil, time, order, reps[i]);
    +
    3651  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    +
    3652 
    +
    3653  REQUIRE( fid >= prevFid );
    +
    3654  prevFid = fid;
    +
    3655  }
    +
    3656  }
    +
    3657  SECTION( "order scaling" ) {
    +
    3658 
    +
    3659  // exclude order 1; too few reps for monotonic increase of accuracy
    +
    3660  int reps = GENERATE( 5, 10 );
    +
    3661 
    +
    3662  // accuracy should increase with increasing repetitions
    +
    3663  int orders[] = {1, 2, 4, 6};
    +
    3664 
    +
    3665  qreal prevFid = 0;
    +
    3666  for (int i=0; i<4; i++) {
    +
    3667  initDebugState(vec);
    +
    3668  applyTrotterCircuit(vec, hamil, time, orders[i], reps);
    +
    3669  qreal fid = calcFidelity(vec, vecRef) / fidNorm;
    +
    3670 
    +
    3671  REQUIRE( fid >= prevFid );
    +
    3672  prevFid = fid;
    +
    3673  }
    +
    3674  }
    +
    3675 
    +
    3676  destroyPauliHamil(hamil);
    +
    3677  }
    +
    3678  }
    +
    3679  SECTION( "input validation" ) {
    +
    3680 
    +
    3681  SECTION( "repetitions" ) {
    +
    3682 
    + +
    3684  int reps = GENERATE( -1, 0 );
    +
    3685 
    +
    3686  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, reps), Contains("repetitions must be >=1") );
    +
    3687 
    +
    3688  destroyPauliHamil(hamil);
    +
    3689  }
    +
    3690  SECTION( "order" ) {
    +
    3691 
    + +
    3693  int order = GENERATE( -1, 0, 3, 5, 7 );
    +
    3694 
    +
    3695  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, order, 1), Contains("order must be 1, or an even number") );
    +
    3696 
    +
    3697  destroyPauliHamil(hamil);
    +
    3698  }
    +
    3699  SECTION( "pauli codes" ) {
    +
    3700 
    +
    3701  int numTerms = 3;
    +
    3702  PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
    +
    3703 
    +
    3704  // make one pauli code wrong
    +
    3705  hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
    +
    3706  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("Invalid Pauli code") );
    +
    3707 
    +
    3708  destroyPauliHamil(hamil);
    +
    3709  }
    +
    3710  SECTION( "matching hamiltonian qubits" ) {
    +
    3711 
    +
    3712  PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
    +
    3713 
    +
    3714  REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), Contains("same number of qubits") );
    +
    3715  REQUIRE_THROWS_WITH( applyTrotterCircuit(mat, hamil, 1, 1, 1), Contains("same number of qubits") );
    +
    3716 
    +
    3717  destroyPauliHamil(hamil);
    +
    3718  }
    +
    3719  }
    +
    3720 
    +
    3721  destroyQureg(vec, QUEST_ENV);
    +
    3722  destroyQureg(mat, QUEST_ENV);
    +
    3723  destroyQureg(vecRef, QUEST_ENV);
    +
    3724  destroyQureg(matRef, QUEST_ENV);
    +
    3725 }
    +
    3726 
    @ INVERSE_PRODUCT
    Definition: QuEST.h:233
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    -
    void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:727
    -
    void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
    Definition: QuEST.c:1101
    -
    void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:814
    -
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1489
    +
    void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:726
    +
    void applyMultiControlledMatrixN(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.
    Definition: QuEST.c:1114
    +
    void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:813
    +
    void initPauliHamil(PauliHamil hamil, qreal *coeffs, enum pauliOpType *codes)
    Initialise PauliHamil instance hamil with the given term coefficients and Pauli codes (one for every ...
    Definition: QuEST.c:1504
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    +
    void applyProjector(Qureg qureg, int qubit, int outcome)
    Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection.
    Definition: QuEST.c:888
    @ PAULI_Z
    Definition: QuEST.h:96
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    @ DISTANCE
    Definition: QuEST.h:234
    -
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1356
    -
    void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:797
    +
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1369
    +
    void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
    Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
    Definition: QuEST.c:796
    @ PAULI_I
    Definition: QuEST.h:96
    int getRandomInt(int min, int max)
    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:526
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    QMatrix getMixedDensityMatrix(std::vector< qreal > probs, std::vector< QVector > states)
    Returns a mixed density matrix formed from mixing the given pure states, which are assumed normalised...
    Definition: utilities.cpp:640
    -
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1516
    -
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1509
    +
    void syncDiagonalOp(DiagonalOp op)
    Update the GPU memory with the current values in op.real and op.imag.
    Definition: QuEST.c:1531
    +
    void destroyDiagonalOp(DiagonalOp op, QuESTEnv env)
    Destroys a DiagonalOp created with createDiagonalOp(), freeing its memory.
    Definition: QuEST.c:1524
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    #define CLEANUP_TEST(quregVec, quregMatr)
    Destroys the data structures made by PREPARE_TEST.
    @ TWOS_COMPLEMENT
    Definition: QuEST.h:269
    -
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
    Definition: QuEST.c:1178
    +
    qreal calcFidelity(Qureg qureg, Qureg pureState)
    Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (n...
    Definition: QuEST.c:1191
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:421
    @ NORM
    Definition: QuEST.h:232
    void setDiagMatrixOverrides(QMatrix &matr, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Modifies the given diagonal matrix such that the diagonal elements which correspond to the coordinate...
    Definition: utilities.cpp:1316
    std::vector< QVector > getRandomOrthonormalVectors(int numQb, int numStates)
    Returns a list of random orthonormal complex vectors, from an undisclosed distribution.
    Definition: utilities.cpp:613
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:175
    @ SCALED_INVERSE_DISTANCE
    Definition: QuEST.h:234
    -
    void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
    Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
    Definition: QuEST.c:1046
    -
    void applyQFT(Qureg qureg, int *qubits, int numQubits)
    Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
    Definition: QuEST.c:867
    +
    void applyPauliHamil(Qureg inQureg, PauliHamil hamil, Qureg outQureg)
    Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary op...
    Definition: QuEST.c:1059
    +
    void applyQFT(Qureg qureg, int *qubits, int numQubits)
    Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.
    Definition: QuEST.c:866
    @ UNSIGNED
    Definition: QuEST.h:269
    -
    void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:744
    +
    void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
    Definition: QuEST.c:743
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    @ INVERSE_DISTANCE
    Definition: QuEST.h:234
    #define qreal
    -
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:686
    +
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:685
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    void toQureg(Qureg qureg, QVector vec)
    Initialises the state-vector qureg to have the same amplitudes as vec.
    Definition: utilities.cpp:1201
    -
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    +
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    @ PAULI_X
    Definition: QuEST.h:96
    TEST_CASE("applyDiagonalOp", "[operators]")
    void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes...
    Definition: utilities.cpp:1229
    @@ -3618,9 +3754,9 @@
    qreal * imag
    The imaginary values of the 2^numQubits complex elements.
    Definition: QuEST.h:310
    phaseFunc
    Flags for specifying named phase functions.
    Definition: QuEST.h:231
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:1113
    -
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
    Definition: QuEST.c:1114
    +
    void applyDiagonalOp(Qureg qureg, DiagonalOp op)
    Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.
    Definition: QuEST.c:1127
    qreal * termCoeffs
    The real coefficient of each Pauli product. This is an array of length PauliHamil....
    Definition: QuEST.h:283
    -
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:1080
    +
    void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general 4-by-4 matrix, which may be non-unitary.
    Definition: QuEST.c:1093
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    ComplexMatrix4 toComplexMatrix4(QMatrix qm)
    Returns a ComplexMatrix4 copy of QMatix qm.
    Definition: utilities.cpp:1027
    @ SCALED_PRODUCT
    Definition: QuEST.h:233
    @@ -3630,37 +3766,38 @@
    @ PAULI_Y
    Definition: QuEST.h:96
    A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
    Definition: QuEST.h:277
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg, freeing its memory.
    Definition: QuEST.c:77
    -
    void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
    Definition: QuEST.c:849
    +
    void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
    Definition: QuEST.c:848
    @ SCALED_INVERSE_SHIFTED_NORM
    Definition: QuEST.h:232
    QVector getRandomStateVector(int numQb)
    Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.
    Definition: utilities.cpp:468
    qreal ** real
    Definition: QuEST.h:189
    -
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1563
    -
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:1035
    +
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1578
    +
    void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
    Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
    Definition: QuEST.c:1048
    QMatrix getRandomQMatrix(int dim)
    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
    Definition: utilities.cpp:379
    -
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:1090
    -
    void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:762
    +
    void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
    Definition: QuEST.c:1103
    +
    void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:761
    @ INVERSE_NORM
    Definition: QuEST.h:232
    long long int getTwosComplement(long long int decimal, int numBits)
    Returns the two's complement signed encoding of the unsigned number decimal, which must be a number b...
    Definition: utilities.cpp:1286
    Represents a system of qubits.
    Definition: QuEST.h:322
    qreal ** imag
    Definition: QuEST.h:190
    @ PRODUCT
    Definition: QuEST.h:233
    -
    void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:779
    +
    void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
    Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
    Definition: QuEST.c:778
    long long int numElemsPerChunk
    The number of the 2^numQubits amplitudes stored on each distributed node.
    Definition: QuEST.h:302
    Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
    Create a new Qureg which is an exact clone of the passed qureg, which can be either a state-vector or...
    Definition: QuEST.c:64
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    ComplexMatrix2 toComplexMatrix2(QMatrix qm)
    Returns a ComplexMatrix2 copy of QMatix qm.
    Definition: utilities.cpp:1021
    -
    void applyFullQFT(Qureg qureg)
    Applies the quantum Fourier transform (QFT) to the entirety of qureg.
    Definition: QuEST.c:877
    +
    void applyFullQFT(Qureg qureg)
    Applies the quantum Fourier transform (QFT) to the entirety of qureg.
    Definition: QuEST.c:876
    Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
    Definition: utilities.cpp:1488
    std::vector< qreal > getRandomProbabilities(int numProbs)
    Returns a list of random real scalars, each in [0, 1], which sum to unity.
    Definition: utilities.cpp:472
    @ SCALED_DISTANCE
    Definition: QuEST.h:234
    qreal * real
    The real values of the 2^numQubits complex elements.
    Definition: QuEST.h:308
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    -
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1399
    +
    void destroyPauliHamil(PauliHamil h)
    Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
    Definition: QuEST.c:1414
    QMatrix getPureDensityMatrix(QVector state)
    Returns a density matrix initialised into the given pure state.
    Definition: utilities.cpp:507
    -
    void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
    Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
    Definition: QuEST.c:832
    +
    QMatrix getRandomDensityMatrix(int numQb)
    Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed sta...
    Definition: utilities.cpp:490
    +
    void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
    Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
    Definition: QuEST.c:831
    @ SCALED_INVERSE_SHIFTED_DISTANCE
    Definition: QuEST.h:234
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:153
    -
    void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general 2-by-2 matrix, which may be non-unitary.
    Definition: QuEST.c:1071
    +
    void applyMatrix2(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general 2-by-2 matrix, which may be non-unitary.
    Definition: QuEST.c:1084
    #define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
    Prepares the needed data structures for unit testing some operators.
    QVector getRandomQVector(int dim)
    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
    Definition: utilities.cpp:435
    @ SCALED_NORM
    Definition: QuEST.h:232
    @@ -3671,12 +3808,12 @@
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
    Definition: QuEST.c:50
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:728
    #define M_PI
    Definition: QuEST_common.c:41
    -
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1057
    -
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1383
    +
    void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
    Applies a trotterisation of unitary evolution to qureg.
    Definition: QuEST.c:1070
    +
    PauliHamil createPauliHamil(int numQubits, int numSumTerms)
    Dynamically allocates a Hamiltonian expressed as a real-weighted sum of products of Pauli operators.
    Definition: QuEST.c:1398
    qcomp getRandomComplex()
    Returns a random complex number within the square closing (-1-i) and (1+i), from a distribution unifo...
    Definition: utilities.cpp:431
    bitEncoding
    Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
    Definition: QuEST.h:269
    -
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1503
    +
    DiagonalOp createDiagonalOp(int numQubits, QuESTEnv env)
    Creates a DiagonalOp representing a diagonal operator on the full Hilbert space of a Qureg.
    Definition: QuEST.c:1518
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:137
    @ SCALED_INVERSE_NORM
    Definition: QuEST.h:232
    diff --git a/docs/test__state__initialisations_8cpp.html b/docs/test__state__initialisations_8cpp.html index 34079e2cb..33e06e533 100644 --- a/docs/test__state__initialisations_8cpp.html +++ b/docs/test__state__initialisations_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/test__state__initialisations_8cpp_source.html b/docs/test__state__initialisations_8cpp_source.html index 908b772c8..1cbaab1aa 100644 --- a/docs/test__state__initialisations_8cpp_source.html +++ b/docs/test__state__initialisations_8cpp_source.html @@ -27,7 +27,7 @@ @@ -322,328 +322,341 @@
    286 TEST_CASE( "initStateFromAmps", "[state_initialisations]" ) {
    287 
    -
    289 
    -
    290  SECTION( "correctness" ) {
    -
    291 
    -
    292  SECTION( "state-vector" ) {
    -
    293 
    -
    294  // create arbitrary (but distinctly non-zero) amplitudes
    -
    295  qreal ampsRe[vec.numAmpsTotal];
    -
    296  qreal ampsIm[vec.numAmpsTotal];
    -
    297  QVector vecRef = QVector(vec.numAmpsTotal);
    -
    298  for (int i=0; i<vec.numAmpsTotal; i++) {
    -
    299  ampsRe[i] = 2*i;
    -
    300  ampsIm[i] = 2*i + 1;
    -
    301  vecRef[i] = (ampsRe[i]) + ampsIm[i] * (qcomp) 1i;;
    -
    302  }
    -
    303 
    -
    304  initBlankState(vec);
    + +
    290 
    +
    291  SECTION( "correctness" ) {
    +
    292 
    +
    293  SECTION( "state-vector" ) {
    +
    294 
    +
    295  // create random (unnormalised) vector
    +
    296  QVector vecRef = getRandomQVector(1<<NUM_QUBITS);
    +
    297 
    +
    298  qreal ampsRe[vec.numAmpsTotal];
    +
    299  qreal ampsIm[vec.numAmpsTotal];
    +
    300  for (size_t i=0; i<vecRef.size(); i++) {
    +
    301  ampsRe[i] = real(vecRef[i]);
    +
    302  ampsIm[i] = imag(vecRef[i]);
    +
    303  }
    +
    304 
    305  initStateFromAmps(vec, ampsRe, ampsIm);
    306  REQUIRE( areEqual(vec, vecRef) );
    307  }
    -
    308  }
    -
    309  SECTION( "input validation" ) {
    -
    310 
    -
    311  SECTION( "density-matrix" ) {
    +
    308  SECTION( "density-matrix" ) {
    +
    309 
    +
    310  // create random (unnormalised) matrix
    +
    311  QMatrix matRef = getRandomQMatrix(1<<NUM_QUBITS);
    312 
    - -
    314  REQUIRE_THROWS_WITH( initStateFromAmps(mat, NULL, NULL), Contains("valid only for state-vectors") );
    -
    315  destroyQureg(mat, QUEST_ENV);
    -
    316  }
    -
    317  }
    -
    318  destroyQureg(vec, QUEST_ENV);
    -
    319 }
    -
    320 
    -
    321 
    -
    322 
    -
    327 TEST_CASE( "initZeroState", "[state_initialisations]" ) {
    -
    328 
    - - -
    331 
    -
    332  SECTION( "correctness" ) {
    -
    333 
    -
    334  SECTION( "state-vector" ) {
    -
    335 
    -
    336  initBlankState(vec);
    -
    337  initZeroState(vec);
    -
    338 
    -
    339  QVector refVec = QVector(vec.numAmpsTotal);
    -
    340  refVec[0] = 1;
    -
    341  REQUIRE( areEqual(vec, refVec) );
    -
    342  }
    -
    343  SECTION( "density-matrix" ) {
    -
    344 
    -
    345  initBlankState(mat);
    -
    346  initZeroState(mat);
    -
    347 
    -
    348  QMatrix refMat = getZeroMatrix(1<<mat.numQubitsRepresented);
    -
    349  refMat[0][0] = 1;
    -
    350  REQUIRE( areEqual(mat, refMat) );
    -
    351  }
    -
    352  }
    -
    353  SECTION( "input validation" ) {
    -
    354 
    -
    355  // no input validation
    -
    356  SUCCEED( );
    -
    357  }
    -
    358  destroyQureg(vec, QUEST_ENV);
    -
    359  destroyQureg(mat, QUEST_ENV);
    -
    360 }
    -
    361 
    -
    362 
    -
    363 
    -
    368 TEST_CASE( "setAmps", "[state_initialisations]" ) {
    -
    369 
    - -
    371 
    -
    372  int maxInd = vec.numAmpsTotal;
    -
    373  qreal reals[maxInd];
    -
    374  qreal imags[maxInd];
    -
    375 
    -
    376  SECTION( "correctness" ) {
    -
    377 
    -
    378  SECTION( "state-vector" ) {
    -
    379 
    -
    380  // all valid number of amplitudes and offsets
    -
    381  int startInd = GENERATE_COPY( range(0,maxInd) );
    -
    382  int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
    -
    383 
    -
    384  // generate random amplitudes
    -
    385  for (int i=0; i<numAmps; i++) {
    -
    386  reals[i] = getRandomReal(-5,5);
    -
    387  imags[i] = getRandomReal(-5,5);
    -
    388  }
    -
    389 
    -
    390  // check both specified and un-specified amplitudes are correctly handled
    -
    391  initDebugState(vec);
    -
    392  QVector vecRef = toQVector(vec);
    -
    393 
    -
    394  setAmps(vec, startInd, reals, imags, numAmps);
    -
    395  for (int i=0; i<numAmps; i++)
    -
    396  vecRef[startInd+i] = reals[i] + imags[i] * (qcomp) 1i;
    -
    397 
    -
    398  REQUIRE( areEqual(vec, vecRef) );
    -
    399  }
    -
    400  }
    -
    401  SECTION( "input validation" ) {
    -
    402 
    -
    403  SECTION( "start index" ) {
    -
    404 
    -
    405  int startInd = GENERATE_COPY( -1, maxInd );
    -
    406  int numAmps = 0;
    -
    407  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
    -
    408  }
    -
    409 
    -
    410  SECTION( "number of amplitudes" ) {
    -
    411 
    -
    412  // independent
    -
    413  int startInd = 0;
    -
    414  int numAmps = GENERATE_COPY( -1, maxInd+1 );
    -
    415  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
    -
    416 
    -
    417  // invalid considering start-index
    -
    418  startInd = maxInd - 1;
    -
    419  numAmps = 2;
    -
    420  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("More amplitudes given than exist") );
    +
    313  qreal ampsRe[mat.numAmpsTotal];
    +
    314  qreal ampsIm[mat.numAmpsTotal];
    +
    315 
    +
    316  // populate column-wise
    +
    317  long long int i=0;
    +
    318  for (size_t c=0; c<matRef.size(); c++) {
    +
    319  for (size_t r=0; r<matRef.size(); r++) {
    +
    320  ampsRe[i] = real(matRef[r][c]);
    +
    321  ampsIm[i] = imag(matRef[r][c]);
    +
    322  i++;
    +
    323  }
    +
    324  }
    +
    325 
    +
    326  initStateFromAmps(mat, ampsRe, ampsIm);
    +
    327  REQUIRE( areEqual(mat, matRef) );
    +
    328  }
    +
    329  }
    +
    330  destroyQureg(vec, QUEST_ENV);
    +
    331  destroyQureg(mat, QUEST_ENV);
    +
    332 }
    +
    333 
    +
    334 
    +
    335 
    +
    340 TEST_CASE( "initZeroState", "[state_initialisations]" ) {
    +
    341 
    + + +
    344 
    +
    345  SECTION( "correctness" ) {
    +
    346 
    +
    347  SECTION( "state-vector" ) {
    +
    348 
    +
    349  initBlankState(vec);
    +
    350  initZeroState(vec);
    +
    351 
    +
    352  QVector refVec = QVector(vec.numAmpsTotal);
    +
    353  refVec[0] = 1;
    +
    354  REQUIRE( areEqual(vec, refVec) );
    +
    355  }
    +
    356  SECTION( "density-matrix" ) {
    +
    357 
    +
    358  initBlankState(mat);
    +
    359  initZeroState(mat);
    +
    360 
    +
    361  QMatrix refMat = getZeroMatrix(1<<mat.numQubitsRepresented);
    +
    362  refMat[0][0] = 1;
    +
    363  REQUIRE( areEqual(mat, refMat) );
    +
    364  }
    +
    365  }
    +
    366  SECTION( "input validation" ) {
    +
    367 
    +
    368  // no input validation
    +
    369  SUCCEED( );
    +
    370  }
    +
    371  destroyQureg(vec, QUEST_ENV);
    +
    372  destroyQureg(mat, QUEST_ENV);
    +
    373 }
    +
    374 
    +
    375 
    +
    376 
    +
    381 TEST_CASE( "setAmps", "[state_initialisations]" ) {
    +
    382 
    + +
    384 
    +
    385  int maxInd = vec.numAmpsTotal;
    +
    386  qreal reals[maxInd];
    +
    387  qreal imags[maxInd];
    +
    388 
    +
    389  SECTION( "correctness" ) {
    +
    390 
    +
    391  SECTION( "state-vector" ) {
    +
    392 
    +
    393  // all valid number of amplitudes and offsets
    +
    394  int startInd = GENERATE_COPY( range(0,maxInd) );
    +
    395  int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
    +
    396 
    +
    397  // generate random amplitudes
    +
    398  for (int i=0; i<numAmps; i++) {
    +
    399  reals[i] = getRandomReal(-5,5);
    +
    400  imags[i] = getRandomReal(-5,5);
    +
    401  }
    +
    402 
    +
    403  // check both specified and un-specified amplitudes are correctly handled
    +
    404  initDebugState(vec);
    +
    405  QVector vecRef = toQVector(vec);
    +
    406 
    +
    407  setAmps(vec, startInd, reals, imags, numAmps);
    +
    408  for (int i=0; i<numAmps; i++)
    +
    409  vecRef[startInd+i] = reals[i] + imags[i] * (qcomp) 1i;
    +
    410 
    +
    411  REQUIRE( areEqual(vec, vecRef) );
    +
    412  }
    +
    413  }
    +
    414  SECTION( "input validation" ) {
    +
    415 
    +
    416  SECTION( "start index" ) {
    +
    417 
    +
    418  int startInd = GENERATE_COPY( -1, maxInd );
    +
    419  int numAmps = 0;
    +
    420  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
    421  }
    -
    422  SECTION( "density-matrix" ) {
    -
    423 
    - -
    425  REQUIRE_THROWS_WITH( setAmps(mat, 0, reals, imags, 0), Contains("valid only for state-vectors") );
    -
    426  destroyQureg(mat, QUEST_ENV);
    -
    427  }
    -
    428  }
    -
    429  destroyQureg(vec, QUEST_ENV);
    -
    430 }
    -
    431 
    -
    432 
    -
    433 
    -
    438 TEST_CASE( "setWeightedQureg", "[state_initialisations]" ) {
    -
    439 
    -
    440  SECTION( "correctness" ) {
    -
    441 
    -
    442  // repeat each test below 10 times
    -
    443  GENERATE( range(0,10) );
    -
    444 
    -
    445  /* note tolerance in areEqual increases with tests, since
    -
    446  * small differences propogate in vecC which is not re-initialised
    -
    447  */
    -
    448 
    -
    449  SECTION( "state-vector" ) {
    -
    450 
    -
    451  // make three random vectors
    - - - -
    455  for (int j=0; j<vecA.numAmpsPerChunk; j++) {
    -
    456  vecA.stateVec.real[j] = getRandomReal(-5,5); vecA.stateVec.imag[j] = getRandomReal(-5,5);
    -
    457  vecB.stateVec.real[j] = getRandomReal(-5,5); vecB.stateVec.imag[j] = getRandomReal(-5,5);
    -
    458  vecC.stateVec.real[j] = getRandomReal(-5,5); vecC.stateVec.imag[j] = getRandomReal(-5,5);
    -
    459  }
    -
    460  copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
    -
    461  QVector refA = toQVector(vecA);
    -
    462  QVector refB = toQVector(vecB);
    -
    463  QVector refC = toQVector(vecC);
    -
    464  QVector refOut;
    -
    465 
    -
    466  // get three random factors
    -
    467  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    468  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    469  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    470  Complex facA = toComplex(numA);
    -
    471  Complex facB = toComplex(numB);
    -
    472  Complex facC = toComplex(numC);
    -
    473 
    -
    474  // check out-qureg is correct, when all quregs are unique...
    -
    475  setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
    -
    476  refOut = numA*refA + numB*refB + numC*refC;
    -
    477  REQUIRE( areEqual(vecC, refOut) );
    +
    422 
    +
    423  SECTION( "number of amplitudes" ) {
    +
    424 
    +
    425  // independent
    +
    426  int startInd = 0;
    +
    427  int numAmps = GENERATE_COPY( -1, maxInd+1 );
    +
    428  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
    +
    429 
    +
    430  // invalid considering start-index
    +
    431  startInd = maxInd - 1;
    +
    432  numAmps = 2;
    +
    433  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("More amplitudes given than exist") );
    +
    434  }
    +
    435  SECTION( "density-matrix" ) {
    +
    436 
    + +
    438  REQUIRE_THROWS_WITH( setAmps(mat, 0, reals, imags, 0), Contains("valid only for state-vectors") );
    +
    439  destroyQureg(mat, QUEST_ENV);
    +
    440  }
    +
    441  }
    +
    442  destroyQureg(vec, QUEST_ENV);
    +
    443 }
    +
    444 
    +
    445 
    +
    446 
    +
    451 TEST_CASE( "setWeightedQureg", "[state_initialisations]" ) {
    +
    452 
    +
    453  SECTION( "correctness" ) {
    +
    454 
    +
    455  // repeat each test below 10 times
    +
    456  GENERATE( range(0,10) );
    +
    457 
    +
    458  /* note tolerance in areEqual increases with tests, since
    +
    459  * small differences propogate in vecC which is not re-initialised
    +
    460  */
    +
    461 
    +
    462  SECTION( "state-vector" ) {
    +
    463 
    +
    464  // make three random vectors
    + + + +
    468  for (int j=0; j<vecA.numAmpsPerChunk; j++) {
    +
    469  vecA.stateVec.real[j] = getRandomReal(-5,5); vecA.stateVec.imag[j] = getRandomReal(-5,5);
    +
    470  vecB.stateVec.real[j] = getRandomReal(-5,5); vecB.stateVec.imag[j] = getRandomReal(-5,5);
    +
    471  vecC.stateVec.real[j] = getRandomReal(-5,5); vecC.stateVec.imag[j] = getRandomReal(-5,5);
    +
    472  }
    +
    473  copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
    +
    474  QVector refA = toQVector(vecA);
    +
    475  QVector refB = toQVector(vecB);
    +
    476  QVector refC = toQVector(vecC);
    +
    477  QVector refOut;
    478 
    -
    479  // ... and that other qureg's aren't modified
    -
    480  REQUIRE( areEqual(vecA, refA) );
    -
    481  REQUIRE( areEqual(vecB, refB) );
    -
    482 
    -
    483  // check quregOut correct, when it's also qureg2
    -
    484  refC = toQVector(vecC);
    -
    485  setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
    -
    486  refOut = numB*refB + numC*refC + numA*refC;
    -
    487  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    -
    488 
    -
    489  // ... and that the remaining qureg is not modified
    -
    490  REQUIRE( areEqual(vecB, refB) );
    +
    479  // get three random factors
    +
    480  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    481  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    482  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    483  Complex facA = toComplex(numA);
    +
    484  Complex facB = toComplex(numB);
    +
    485  Complex facC = toComplex(numC);
    +
    486 
    +
    487  // check out-qureg is correct, when all quregs are unique...
    +
    488  setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
    +
    489  refOut = numA*refA + numB*refB + numC*refC;
    +
    490  REQUIRE( areEqual(vecC, refOut) );
    491 
    -
    492  // check quregOut correct, when it's also qureg1
    -
    493  refC = toQVector(vecC);
    -
    494  setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
    -
    495  refOut = numC*refC + numB*refB + numA*refC;
    -
    496  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    -
    497 
    -
    498  // ... and that the remaining qureg is not modified
    -
    499  REQUIRE( areEqual(vecB, refB) );
    -
    500 
    -
    501  // check quregOut is correct when it's both input quregs
    -
    502  refC = toQVector(vecC);
    -
    503  setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
    -
    504  refOut = numA*refC + numB*refC + numC*refC;
    -
    505  REQUIRE( areEqual(vecC, refOut, 1E3*REAL_EPS) );
    -
    506 
    -
    507  // cleanup
    -
    508  destroyQureg(vecA, QUEST_ENV);
    -
    509  destroyQureg(vecB, QUEST_ENV);
    -
    510  destroyQureg(vecC, QUEST_ENV);
    -
    511  }
    -
    512  SECTION( "density-matrix" ) {
    +
    492  // ... and that other qureg's aren't modified
    +
    493  REQUIRE( areEqual(vecA, refA) );
    +
    494  REQUIRE( areEqual(vecB, refB) );
    +
    495 
    +
    496  // check quregOut correct, when it's also qureg2
    +
    497  refC = toQVector(vecC);
    +
    498  setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
    +
    499  refOut = numB*refB + numC*refC + numA*refC;
    +
    500  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    +
    501 
    +
    502  // ... and that the remaining qureg is not modified
    +
    503  REQUIRE( areEqual(vecB, refB) );
    +
    504 
    +
    505  // check quregOut correct, when it's also qureg1
    +
    506  refC = toQVector(vecC);
    +
    507  setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
    +
    508  refOut = numC*refC + numB*refB + numA*refC;
    +
    509  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
    +
    510 
    +
    511  // ... and that the remaining qureg is not modified
    +
    512  REQUIRE( areEqual(vecB, refB) );
    513 
    -
    514  // make three random matrices
    - - - -
    518  for (int j=0; j<matA.numAmpsPerChunk; j++) {
    -
    519  matA.stateVec.real[j] = getRandomReal(-5,5); matA.stateVec.imag[j] = getRandomReal(-5,5);
    -
    520  matB.stateVec.real[j] = getRandomReal(-5,5); matB.stateVec.imag[j] = getRandomReal(-5,5);
    -
    521  matC.stateVec.real[j] = getRandomReal(-5,5); matC.stateVec.imag[j] = getRandomReal(-5,5);
    -
    522  }
    -
    523  copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
    -
    524  QMatrix refA = toQMatrix(matA);
    -
    525  QMatrix refB = toQMatrix(matB);
    -
    526  QMatrix refC = toQMatrix(matC);
    -
    527  QMatrix refOut;
    -
    528 
    -
    529  // get three random factors
    -
    530  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    531  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    532  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    -
    533  Complex facA = toComplex(numA);
    -
    534  Complex facB = toComplex(numB);
    -
    535  Complex facC = toComplex(numC);
    -
    536 
    -
    537  // check out-qureg is correct, when all quregs are unique...
    -
    538  setWeightedQureg(facA, matA, facB, matB, facC, matC);
    -
    539  refOut = numA*refA + numB*refB + numC*refC;
    -
    540  REQUIRE( areEqual(matC, refOut) );
    +
    514  // check quregOut is correct when it's both input quregs
    +
    515  refC = toQVector(vecC);
    +
    516  setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
    +
    517  refOut = numA*refC + numB*refC + numC*refC;
    +
    518  REQUIRE( areEqual(vecC, refOut, 1E3*REAL_EPS) );
    +
    519 
    +
    520  // cleanup
    +
    521  destroyQureg(vecA, QUEST_ENV);
    +
    522  destroyQureg(vecB, QUEST_ENV);
    +
    523  destroyQureg(vecC, QUEST_ENV);
    +
    524  }
    +
    525  SECTION( "density-matrix" ) {
    +
    526 
    +
    527  // make three random matrices
    + + + +
    531  for (int j=0; j<matA.numAmpsPerChunk; j++) {
    +
    532  matA.stateVec.real[j] = getRandomReal(-5,5); matA.stateVec.imag[j] = getRandomReal(-5,5);
    +
    533  matB.stateVec.real[j] = getRandomReal(-5,5); matB.stateVec.imag[j] = getRandomReal(-5,5);
    +
    534  matC.stateVec.real[j] = getRandomReal(-5,5); matC.stateVec.imag[j] = getRandomReal(-5,5);
    +
    535  }
    +
    536  copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
    +
    537  QMatrix refA = toQMatrix(matA);
    +
    538  QMatrix refB = toQMatrix(matB);
    +
    539  QMatrix refC = toQMatrix(matC);
    +
    540  QMatrix refOut;
    541 
    -
    542  // ... and that other qureg's aren't modified
    -
    543  REQUIRE( areEqual(matA, refA) );
    -
    544  REQUIRE( areEqual(matB, refB) );
    -
    545 
    -
    546  // check quregOut correct, when it's also qureg2
    -
    547  refC = toQMatrix(matC);
    -
    548  setWeightedQureg(facB, matB, facC, matC, facA, matC);
    -
    549  refOut = numB*refB + numC*refC + numA*refC;
    -
    550  REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
    -
    551 
    -
    552  // ... and that the remaining qureg is not modified
    -
    553  REQUIRE( areEqual(matB, refB) );
    +
    542  // get three random factors
    +
    543  qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    544  qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    545  qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
    +
    546  Complex facA = toComplex(numA);
    +
    547  Complex facB = toComplex(numB);
    +
    548  Complex facC = toComplex(numC);
    +
    549 
    +
    550  // check out-qureg is correct, when all quregs are unique...
    +
    551  setWeightedQureg(facA, matA, facB, matB, facC, matC);
    +
    552  refOut = numA*refA + numB*refB + numC*refC;
    +
    553  REQUIRE( areEqual(matC, refOut) );
    554 
    -
    555  // check quregOut correct, when it's also qureg1
    -
    556  refC = toQMatrix(matC);
    -
    557  setWeightedQureg(facC, matC, facB, matB, facA, matC);
    -
    558  refOut = numC*refC + numB*refB + numA*refC;
    -
    559  REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
    -
    560 
    -
    561  // ... and that the remaining qureg is not modified
    -
    562  REQUIRE( areEqual(matB, refB) );
    -
    563 
    -
    564  // check quregOut is correct when it's both input quregs
    -
    565  refC = toQMatrix(matC);
    -
    566  setWeightedQureg(facA, matC, facB, matC, facC, matC);
    -
    567  refOut = numA*refC + numB*refC + numC*refC;
    -
    568  REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
    -
    569 
    -
    570  // cleanup
    -
    571  destroyQureg(matA, QUEST_ENV);
    -
    572  destroyQureg(matB, QUEST_ENV);
    -
    573  destroyQureg(matC, QUEST_ENV);
    -
    574  }
    -
    575  }
    -
    576  SECTION( "input validation" ) {
    -
    577 
    -
    578  SECTION( "qureg types" ) {
    -
    579 
    - - -
    582  Complex f = {.real=0, .imag=0};
    -
    583 
    -
    584  // two state-vecs, one density-matrix
    -
    585  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    586  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    587  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    588 
    -
    589  // one state-vec, two density-matrices
    -
    590  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    591  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    -
    592  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    -
    593 
    -
    594  destroyQureg(vec, QUEST_ENV);
    -
    595  destroyQureg(mat, QUEST_ENV);
    -
    596  }
    -
    597  SECTION( "qureg dimensions" ) {
    -
    598 
    - -
    600  Qureg vecB = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    - - -
    603  Complex f = {.real=0, .imag=0};
    -
    604 
    -
    605  // state-vecs
    -
    606  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), Contains("Dimensions") );
    -
    607  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), Contains("Dimensions") );
    -
    608  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), Contains("Dimensions") );
    -
    609 
    -
    610  // density-matrices
    -
    611  REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), Contains("Dimensions") );
    -
    612  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), Contains("Dimensions") );
    -
    613  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), Contains("Dimensions") );
    -
    614 
    -
    615  destroyQureg(vecA, QUEST_ENV);
    -
    616  destroyQureg(vecB, QUEST_ENV);
    -
    617  destroyQureg(matA, QUEST_ENV);
    -
    618  destroyQureg(matB, QUEST_ENV);
    -
    619  }
    -
    620  }
    -
    621 }
    -
    622 
    +
    555  // ... and that other qureg's aren't modified
    +
    556  REQUIRE( areEqual(matA, refA) );
    +
    557  REQUIRE( areEqual(matB, refB) );
    +
    558 
    +
    559  // check quregOut correct, when it's also qureg2
    +
    560  refC = toQMatrix(matC);
    +
    561  setWeightedQureg(facB, matB, facC, matC, facA, matC);
    +
    562  refOut = numB*refB + numC*refC + numA*refC;
    +
    563  REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
    +
    564 
    +
    565  // ... and that the remaining qureg is not modified
    +
    566  REQUIRE( areEqual(matB, refB) );
    +
    567 
    +
    568  // check quregOut correct, when it's also qureg1
    +
    569  refC = toQMatrix(matC);
    +
    570  setWeightedQureg(facC, matC, facB, matB, facA, matC);
    +
    571  refOut = numC*refC + numB*refB + numA*refC;
    +
    572  REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
    +
    573 
    +
    574  // ... and that the remaining qureg is not modified
    +
    575  REQUIRE( areEqual(matB, refB) );
    +
    576 
    +
    577  // check quregOut is correct when it's both input quregs
    +
    578  refC = toQMatrix(matC);
    +
    579  setWeightedQureg(facA, matC, facB, matC, facC, matC);
    +
    580  refOut = numA*refC + numB*refC + numC*refC;
    +
    581  REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
    +
    582 
    +
    583  // cleanup
    +
    584  destroyQureg(matA, QUEST_ENV);
    +
    585  destroyQureg(matB, QUEST_ENV);
    +
    586  destroyQureg(matC, QUEST_ENV);
    +
    587  }
    +
    588  }
    +
    589  SECTION( "input validation" ) {
    +
    590 
    +
    591  SECTION( "qureg types" ) {
    +
    592 
    + + +
    595  Complex f = {.real=0, .imag=0};
    +
    596 
    +
    597  // two state-vecs, one density-matrix
    +
    598  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    +
    599  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    +
    600  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    +
    601 
    +
    602  // one state-vec, two density-matrices
    +
    603  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    +
    604  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
    +
    605  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
    +
    606 
    +
    607  destroyQureg(vec, QUEST_ENV);
    +
    608  destroyQureg(mat, QUEST_ENV);
    +
    609  }
    +
    610  SECTION( "qureg dimensions" ) {
    +
    611 
    + +
    613  Qureg vecB = createQureg(NUM_QUBITS + 1, QUEST_ENV);
    + + +
    616  Complex f = {.real=0, .imag=0};
    +
    617 
    +
    618  // state-vecs
    +
    619  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), Contains("Dimensions") );
    +
    620  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), Contains("Dimensions") );
    +
    621  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), Contains("Dimensions") );
    +
    622 
    +
    623  // density-matrices
    +
    624  REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), Contains("Dimensions") );
    +
    625  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), Contains("Dimensions") );
    +
    626  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), Contains("Dimensions") );
    +
    627 
    +
    628  destroyQureg(vecA, QUEST_ENV);
    +
    629  destroyQureg(vecB, QUEST_ENV);
    +
    630  destroyQureg(matA, QUEST_ENV);
    +
    631  destroyQureg(matB, QUEST_ENV);
    +
    632  }
    +
    633  }
    +
    634 }
    +
    635 
    void initBlankState(Qureg qureg)
    Initialises a qureg to have all-zero-amplitudes.
    Definition: QuEST.c:119
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    @@ -651,20 +664,21 @@
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:421
    -
    void cloneQureg(Qureg targetQureg, Qureg copyQureg)
    Overwrite the amplitudes of targetQureg with those from copyQureg.
    Definition: QuEST.c:165
    +
    void cloneQureg(Qureg targetQureg, Qureg copyQureg)
    Overwrite the amplitudes of targetQureg with those from copyQureg.
    Definition: QuEST.c:164
    #define qreal
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    -
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
    Definition: QuEST.c:1008
    -
    void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
    Definition: QuEST.c:1024
    +
    void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
    Overwrites a subset of the amplitudes in state-vector qureg, with those passed in reals and imags.
    Definition: QuEST.c:1021
    +
    void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
    Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
    Definition: QuEST.c:1037
    std::vector< qcomp > QVector
    A complex vector, which can be zero-initialised with QVector(numAmps).
    Definition: utilities.hpp:60
    QVector toQVector(Qureg qureg)
    Returns an equal-size copy of the given state-vector qureg.
    Definition: utilities.cpp:1113
    long long int numAmpsPerChunk
    Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
    Definition: QuEST.h:332
    #define qcomp
    -
    void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
    Initialise state-vector qureg by specifying all amplitudes.
    Definition: QuEST.c:157
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    +
    void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
    Initialise qureg by specifying all amplitudes.
    Definition: QuEST.c:157
    +
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:42
    #define toComplex(scalar)
    void destroyQureg(Qureg qureg, QuESTEnv env)
    Deallocate a Qureg, freeing its memory.
    Definition: QuEST.c:77
    -
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1563
    +
    void initDebugState(Qureg qureg)
    Initialises qureg to be in the un-normalised, non-physical state with with -th complex amplitude give...
    Definition: QuEST.c:1578
    +
    QMatrix getRandomQMatrix(int dim)
    Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
    Definition: utilities.cpp:379
    void initClassicalState(Qureg qureg, long long int stateInd)
    Initialise qureg into the classical state (also known as a "computational basis state") with index st...
    Definition: QuEST.c:134
    Represents a system of qubits.
    Definition: QuEST.h:322
    ComplexArray stateVec
    Computational state amplitudes - a subset thereof in the MPI version.
    Definition: QuEST.h:341
    @@ -675,6 +689,7 @@
    Qureg createQureg(int numQubits, QuESTEnv env)
    Creates a state-vector Qureg object representing a set of qubits which will remain in a pure state.
    Definition: QuEST.c:36
    QMatrix getZeroMatrix(size_t dim)
    Returns a dim-by-dim square complex matrix, initialised to all zeroes.
    Definition: utilities.cpp:153
    Represents one complex number.
    Definition: QuEST.h:103
    +
    QVector getRandomQVector(int dim)
    Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
    Definition: utilities.cpp:435
    void initZeroState(Qureg qureg)
    Initialise qureg into the zero state.
    Definition: QuEST.c:113
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:398
    Qureg createDensityQureg(int numQubits, QuESTEnv env)
    Creates a density matrix Qureg object representing a set of qubits which can enter noisy and mixed st...
    Definition: QuEST.c:50
    diff --git a/docs/test__unitaries_8cpp.html b/docs/test__unitaries_8cpp.html index 36d7cc93e..77afb8450 100644 --- a/docs/test__unitaries_8cpp.html +++ b/docs/test__unitaries_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/test__unitaries_8cpp_source.html b/docs/test__unitaries_8cpp_source.html index 33d395aad..693ac20e3 100644 --- a/docs/test__unitaries_8cpp_source.html +++ b/docs/test__unitaries_8cpp_source.html @@ -27,7 +27,7 @@ @@ -2650,96 +2650,96 @@
    2773  CLEANUP_TEST( quregVec, quregMatr );
    2774 }
    -
    void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
    Definition: QuEST.c:245
    +
    void controlledRotateZ(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
    Definition: QuEST.c:244
    Represents a 3-vector of real numbers.
    Definition: QuEST.h:198
    pauliOpType
    Codes for specifying Pauli operators.
    Definition: QuEST.h:96
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:304
    -
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:257
    -
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:221
    +
    void twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:256
    +
    void controlledRotateX(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:220
    qreal real[4][4]
    Definition: QuEST.h:177
    #define CLEANUP_TEST(quregVec, quregMatr)
    Destroys the data structures made by PREPARE_TEST.
    @ PAULI_Z
    Definition: QuEST.h:96
    -
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:602
    +
    void rotateAroundAxis(Qureg qureg, int rotQubit, qreal angle, Vector axis)
    Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
    Definition: QuEST.c:601
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    -
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1356
    +
    void destroyComplexMatrixN(ComplexMatrixN m)
    Destroy a ComplexMatrixN instance created with createComplexMatrixN()
    Definition: QuEST.c:1369
    @ PAULI_I
    Definition: QuEST.h:96
    -
    void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple control and target qubits.
    Definition: QuEST.c:550
    +
    void multiControlledMultiQubitNot(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple control and target qubits.
    Definition: QuEST.c:549
    int getRandomInt(int min, int max)
    Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:526
    TEST_CASE("compactUnitary", "[unitaries]")
    -
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1335
    -
    void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
    Definition: QuEST.c:615
    +
    ComplexMatrixN createComplexMatrixN(int numQubits)
    Allocate dynamic memory for a square complex matrix of any size, which can be passed to functions lik...
    Definition: QuEST.c:1348
    +
    void controlledRotateAroundAxis(Qureg qureg, int controlQubit, int targetQubit, qreal angle, Vector axis)
    Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
    Definition: QuEST.c:614
    qreal z
    Definition: QuEST.h:200
    -
    void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general multi-controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:283
    +
    void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general multi-controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:282
    #define NUM_QUBITS
    The default number of qubits in the registers created for unit testing (both statevectors and density...
    Definition: utilities.hpp:36
    QMatrix getRandomUnitary(int numQb)
    Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix.
    Definition: utilities.cpp:530
    qreal getRandomReal(qreal min, qreal max)
    Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
    Definition: utilities.cpp:421
    -
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:349
    -
    void sGate(Qureg qureg, int targetQubit)
    Apply the single-qubit S gate.
    Definition: QuEST.c:466
    +
    void unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary (including a global phase factor).
    Definition: QuEST.c:348
    +
    void sGate(Qureg qureg, int targetQubit)
    Apply the single-qubit S gate.
    Definition: QuEST.c:465
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:175
    -
    void rotateY(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:199
    -
    void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Introduce a phase factor on state of the passed qubits.
    Definition: QuEST.c:511
    +
    void rotateY(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:198
    +
    void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
    Introduce a phase factor on state of the passed qubits.
    Definition: QuEST.c:510
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    #define qreal
    -
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:686
    +
    void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-qubit multi-Pauli rotation, also known as a Pauli gadget, on a selected number of qubit...
    Definition: QuEST.c:685
    QMatrix toQMatrix(ComplexMatrix2 src)
    Returns a copy of the given 2-by-2 matrix.
    Definition: utilities.cpp:1044
    -
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    -
    void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
    Definition: QuEST.c:588
    -
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:297
    +
    unsigned int calcLog2(long unsigned int num)
    returns log2 of numbers which must be gauranteed to be 2^n
    +
    void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
    Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
    Definition: QuEST.c:587
    +
    void multiQubitUnitary(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
    Definition: QuEST.c:296
    #define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
    Prepares the needed data structures for unit testing unitaries.
    -
    void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
    Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
    Definition: QuEST.c:669
    +
    void multiControlledMultiRotateZ(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, int numTargets, qreal angle)
    Apply a multi-controlled multi-target Z rotation, also known as a controlled phase gadget.
    Definition: QuEST.c:668
    @ PAULI_X
    Definition: QuEST.h:96
    -
    void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
    Definition: QuEST.c:564
    +
    void controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
    Definition: QuEST.c:563
    QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
    Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrice...
    Definition: utilities.cpp:216
    -
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:331
    +
    void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:330
    void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
    Initialises cm with the values of qm.
    Definition: utilities.cpp:1033
    -
    void rotateX(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:188
    -
    void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
    Definition: QuEST.c:706
    +
    void rotateX(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
    Definition: QuEST.c:187
    +
    void multiControlledMultiRotatePauli(Qureg qureg, int *controlQubits, int numControls, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
    Apply a multi-controlled multi-target multi-Pauli rotation, also known as a controlled Pauli gadget.
    Definition: QuEST.c:705
    qreal y
    Definition: QuEST.h:200
    qcomp expI(qreal phase)
    Returns the unit-norm complex number exp(i*phase).
    Definition: utilities.cpp:417
    qreal x
    Definition: QuEST.h:200
    -
    void pauliZ(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
    Definition: QuEST.c:455
    -
    void swapGate(Qureg qureg, int qb1, int qb2)
    Performs a SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:628
    +
    void pauliZ(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
    Definition: QuEST.c:454
    +
    void swapGate(Qureg qureg, int qb1, int qb2)
    Performs a SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:627
    #define qcomp
    ComplexMatrix4 toComplexMatrix4(QMatrix qm)
    Returns a ComplexMatrix4 copy of QMatix qm.
    Definition: utilities.cpp:1027
    #define toComplex(scalar)
    -
    void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
    Definition: QuEST.c:576
    +
    void controlledPhaseFlip(Qureg qureg, int idQubit1, int idQubit2)
    Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
    Definition: QuEST.c:575
    @ PAULI_Y
    Definition: QuEST.h:96
    -
    void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:314
    -
    void multiQubitNot(Qureg qureg, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
    Definition: QuEST.c:537
    +
    void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, int numTargs, ComplexMatrixN u)
    Apply a general controlled multi-qubit unitary (including a global phase factor).
    Definition: QuEST.c:313
    +
    void multiQubitNot(Qureg qureg, int *targs, int numTargs)
    Apply a NOT (or Pauli X) gate with multiple target qubits, which has the same effect as (but is much ...
    Definition: QuEST.c:536
    qreal ** real
    Definition: QuEST.h:189
    -
    void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    Apply a single-qubit unitary parameterised by two given complex scalars.
    Definition: QuEST.c:405
    -
    void pauliY(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
    Definition: QuEST.c:444
    +
    void compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
    Apply a single-qubit unitary parameterised by two given complex scalars.
    Definition: QuEST.c:404
    +
    void pauliY(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
    Definition: QuEST.c:443
    Represents a system of qubits.
    Definition: QuEST.h:322
    -
    void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Introduce a phase factor on state of qubits idQubit1 and idQubit2.
    Definition: QuEST.c:499
    -
    void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    Apply a general controlled unitary (single control, single target), which can include a global phase ...
    Definition: QuEST.c:361
    +
    void controlledPhaseShift(Qureg qureg, int idQubit1, int idQubit2, qreal angle)
    Introduce a phase factor on state of qubits idQubit1 and idQubit2.
    Definition: QuEST.c:498
    +
    void controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
    Apply a general controlled unitary (single control, single target), which can include a global phase ...
    Definition: QuEST.c:360
    qreal ** imag
    Definition: QuEST.h:190
    -
    void phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Shift the phase between and of a single qubit by a given angle.
    Definition: QuEST.c:488
    -
    void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled not (single control, single target) gate, also known as the c-X,...
    Definition: QuEST.c:525
    +
    void phaseShift(Qureg qureg, int targetQubit, qreal angle)
    Shift the phase between and of a single qubit by a given angle.
    Definition: QuEST.c:487
    +
    void controlledNot(Qureg qureg, int controlQubit, int targetQubit)
    Apply the controlled not (single control, single target) gate, also known as the c-X,...
    Definition: QuEST.c:524
    qreal real[2][2]
    Definition: QuEST.h:139
    -
    void pauliX(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
    Definition: QuEST.c:433
    +
    void pauliX(Qureg qureg, int targetQubit)
    Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
    Definition: QuEST.c:432
    std::vector< std::vector< qcomp > > QMatrix
    A complex square matrix.
    Definition: utilities.hpp:49
    -
    void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:270
    +
    void controlledTwoQubitUnitary(Qureg qureg, int controlQubit, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
    Apply a general controlled two-qubit unitary (including a global phase factor).
    Definition: QuEST.c:269
    ComplexMatrix2 toComplexMatrix2(QMatrix qm)
    Returns a ComplexMatrix2 copy of QMatix qm.
    Definition: utilities.cpp:1021
    Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
    Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
    Definition: utilities.cpp:1488
    qreal real
    Definition: QuEST.h:105
    -
    void tGate(Qureg qureg, int targetQubit)
    Apply the single-qubit T gate.
    Definition: QuEST.c:477
    -
    void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
    Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
    Definition: QuEST.c:653
    +
    void tGate(Qureg qureg, int targetQubit)
    Apply the single-qubit T gate.
    Definition: QuEST.c:476
    +
    void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
    Apply a multi-qubit Z rotation, also known as a phase gadget, on a selected number of qubits.
    Definition: QuEST.c:652
    QMatrix getExponentialOfDiagonalMatrix(QMatrix a)
    Returns the matrix exponential of a diagonal, square, complex matrix.
    Definition: utilities.cpp:197
    -
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:177
    +
    void hadamard(Qureg qureg, int targetQubit)
    Apply the single-qubit Hadamard gate.
    Definition: QuEST.c:176
    Represents one complex number.
    Definition: QuEST.h:103
    -
    void rotateZ(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
    Definition: QuEST.c:210
    -
    void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general multiple-control single-target unitary, which can include a global phase factor.
    Definition: QuEST.c:374
    +
    void rotateZ(Qureg qureg, int targetQubit, qreal angle)
    Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
    Definition: QuEST.c:209
    +
    void multiControlledUnitary(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general multiple-control single-target unitary, which can include a global phase factor.
    Definition: QuEST.c:373
    bool areEqual(QVector a, QVector b)
    Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
    Definition: utilities.cpp:398
    void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
    Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
    Definition: utilities.cpp:728
    #define M_PI
    Definition: QuEST_common.c:41
    Catch::Generators::GeneratorWrapper< int * > bitsets(int numBits)
    Returns a Catch2 generator of every numBits-length bit-set, in increasing lexographic order,...
    Definition: utilities.cpp:1557
    -
    void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
    Definition: QuEST.c:418
    -
    void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
    Definition: QuEST.c:389
    -
    void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Performs a sqrt SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:640
    +
    void controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
    Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
    Definition: QuEST.c:417
    +
    void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, int numControlQubits, int targetQubit, ComplexMatrix2 u)
    Apply a general single-qubit unitary with multiple control qubits, conditioned upon a specific bit se...
    Definition: QuEST.c:388
    +
    void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
    Performs a sqrt SWAP gate between qubit1 and qubit2.
    Definition: QuEST.c:639
    Represents a 2x2 matrix of complex numbers.
    Definition: QuEST.h:137
    -
    void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:233
    +
    void controlledRotateY(Qureg qureg, int controlQubit, int targetQubit, qreal angle)
    Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
    Definition: QuEST.c:232
    diff --git a/docs/todo.html b/docs/todo.html index e0158bfcc..3c359f6f5 100644 --- a/docs/todo.html +++ b/docs/todo.html @@ -27,7 +27,7 @@ diff --git a/docs/utilities_8cpp.html b/docs/utilities_8cpp.html index 1407a8c46..66ff58a4f 100644 --- a/docs/utilities_8cpp.html +++ b/docs/utilities_8cpp.html @@ -27,7 +27,7 @@ diff --git a/docs/utilities_8cpp_source.html b/docs/utilities_8cpp_source.html index 6213f25bb..26497b280 100644 --- a/docs/utilities_8cpp_source.html +++ b/docs/utilities_8cpp_source.html @@ -27,7 +27,7 @@ @@ -1629,15 +1629,15 @@
    QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
    Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
    Definition: utilities.cpp:304
    long long int getUnsigned(long long int twosComp, int numBits)
    Return the unsigned value of a number, made of #numBits bits, which under two's complement,...
    Definition: utilities.cpp:1298
    -
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:39
    +
    void copyStateFromGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from GPU memory (qureg....
    Definition: QuEST_cpu.c:45
    QuESTEnv QUEST_ENV
    The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
    Definition: main.cpp:20
    -
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    +
    void syncQuESTEnv(QuESTEnv env)
    Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
    @ PAULI_Z
    Definition: QuEST.h:96
    QVector getKroneckerProduct(QVector b, QVector a)
    Returns b (otimes) a.
    Definition: utilities.cpp:143
    SequenceGenerator(T maxDigit_, int numDigits)
    Definition: utilities.cpp:1527
    -
    int rank
    Definition: QuEST.h:363
    +
    int rank
    Definition: QuEST.h:364
    void operator+=(QVector &v1, const QVector &v2)
    Definition: utilities.cpp:64
    #define macro_copyComplexMatrix(dest, src)
    Copies ComplexMatrix structures into a QMatrix.
    Definition: utilities.cpp:1039
    @@ -1691,7 +1691,7 @@
    #define qcomp
    enum pauliOpType * pauliCodes
    The Pauli operators acting on each qubit, flattened over every operator.
    Definition: QuEST.h:281
    ComplexMatrix4 toComplexMatrix4(QMatrix qm)
    Returns a ComplexMatrix4 copy of QMatix qm.
    Definition: utilities.cpp:1027
    -
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:36
    +
    void copyStateToGPU(Qureg qureg)
    In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
    Definition: QuEST_cpu.c:42
    void operator*=(QVector &v1, const qcomp &a)
    Definition: utilities.cpp:70
    QMatrix toDiagonalQMatrix(QVector vec)
    Returns a diagonal complex matrix formed by the given vector.
    Definition: utilities.cpp:1309
    int numQubits
    The number of qubits this operator can act on (informing its size)
    Definition: QuEST.h:300
    diff --git a/docs/utilities_8hpp.html b/docs/utilities_8hpp.html index 8551d10bb..74e6709ee 100644 --- a/docs/utilities_8hpp.html +++ b/docs/utilities_8hpp.html @@ -27,7 +27,7 @@ diff --git a/docs/utilities_8hpp_source.html b/docs/utilities_8hpp_source.html index 083fd45b2..5ff93f60e 100644 --- a/docs/utilities_8hpp_source.html +++ b/docs/utilities_8hpp_source.html @@ -27,7 +27,7 @@ @@ -326,11 +326,11 @@
    void operator/=(QVector &v1, const qcomp &a)
    Definition: utilities.cpp:73
    std::vector< QVector > getRandomOrthonormalVectors(int numQb, int numStates)
    Returns a list of random orthonormal complex vectors, from an undisclosed distribution.
    Definition: utilities.cpp:613
    Represents a 4x4 matrix of complex numbers.
    Definition: QuEST.h:175
    -
    Information about the environment the program is running in.
    Definition: QuEST.h:361
    +
    Information about the environment the program is running in.
    Definition: QuEST.h:362
    Represents a general 2^N by 2^N matrix of complex numbers.
    Definition: QuEST.h:186
    #define qreal
    void toQureg(Qureg qureg, QVector vec)
    Initialises the state-vector qureg to have the same amplitudes as vec.
    Definition: utilities.cpp:1201
    -
    unsigned int calcLog2(long unsigned int res)
    Returns log2 of numbers which must be gauranteed to be 2^n.
    +
    unsigned int calcLog2(long unsigned int res)
    Returns log2 of numbers which must be gauranteed to be 2^n.
    QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
    Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrice...
    Definition: utilities.cpp:216
    void setUniqueFilename(char *outFn, char *prefix)
    Modifies outFn to be a filename of format prefix_NUM.txt where NUM is a new unique integer so far.
    Definition: utilities.cpp:1358
    void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
    Populates the coeffs array with random qreals in (-5, 5), and populates codes with random Pauli codes...
    Definition: utilities.cpp:1229