QuEST_internal.h File Reference
#include "QuEST.h"
#include "QuEST_precision.h"

Go to the source code of this file.

Functions

void conjugateMatrixN (ComplexMatrixN u)
 
qreal densmatr_calcFidelity (Qureg qureg, Qureg pureState)
 
qreal densmatr_calcHilbertSchmidtDistance (Qureg a, Qureg b)
 
qreal densmatr_calcInnerProduct (Qureg a, Qureg b)
 
qreal densmatr_calcProbOfOutcome (Qureg qureg, const int measureQubit, int outcome)
 
qreal densmatr_calcPurity (Qureg qureg)
 Computes the trace of the density matrix squared. More...
 
qreal densmatr_calcTotalProb (Qureg qureg)
 
void densmatr_collapseToKnownProbOutcome (Qureg qureg, const int measureQubit, int outcome, qreal outcomeProb)
 Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero. More...
 
void densmatr_initClassicalState (Qureg qureg, long long int stateInd)
 
void densmatr_initPlusState (Qureg targetQureg)
 
void densmatr_initPureState (Qureg targetQureg, Qureg copyQureg)
 
int densmatr_measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 
void densmatr_mixDamping (Qureg qureg, const int targetQubit, qreal damping)
 
void densmatr_mixDensityMatrix (Qureg combineQureg, qreal otherProb, Qureg otherQureg)
 
void densmatr_mixDephasing (Qureg qureg, const int targetQubit, qreal dephase)
 
void densmatr_mixDepolarising (Qureg qureg, const int targetQubit, qreal depolLevel)
 
void densmatr_mixKrausMap (Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
 
void densmatr_mixMultiQubitKrausMap (Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
 
void densmatr_mixPauli (Qureg qureg, int qubit, qreal pX, qreal pY, qreal pZ)
 
void densmatr_mixTwoQubitDephasing (Qureg qureg, const int qubit1, const int qubit2, qreal dephase)
 
void densmatr_mixTwoQubitDepolarising (Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
 
void densmatr_mixTwoQubitKrausMap (Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
 
void ensureIndsIncrease (int *ind1, int *ind2)
 
void getComplexPairAndPhaseFromUnitary (ComplexMatrix2 u, Complex *alpha, Complex *beta, qreal *globalPhase)
 maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta) More...
 
void getComplexPairFromRotation (qreal angle, Vector axis, Complex *alpha, Complex *beta)
 
ComplexMatrix2 getConjugateMatrix2 (ComplexMatrix2 src)
 
ComplexMatrix4 getConjugateMatrix4 (ComplexMatrix4 src)
 
Complex getConjugateScalar (Complex scalar)
 
long long int getControlFlipMask (int *controlQubits, int *controlState, const int numControlQubits)
 
long long int getQubitBitMask (int *controlQubits, const int numControlQubits)
 
void getQuESTDefaultSeedKey (unsigned long int *key)
 
qreal getVectorMagnitude (Vector vec)
 
void getZYZRotAnglesFromComplexPair (Complex alpha, Complex beta, qreal *rz2, qreal *ry, qreal *rz1)
 maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1) More...
 
unsigned long int hashString (char *str)
 
void setConjugateMatrixN (ComplexMatrixN m)
 
void shiftIndices (int *indices, int numIndices, int shift)
 
void statevec_applyPauliSum (Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
 
qreal statevec_calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
 
qreal statevec_calcExpecPauliSum (Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
 
qreal statevec_calcFidelity (Qureg qureg, Qureg pureState)
 
Complex statevec_calcInnerProduct (Qureg bra, Qureg ket)
 Terrible code which unnecessarily individually computes and sums the real and imaginary components of the inner product, so as to not have to worry about keeping the sums separated during reduction. More...
 
qreal statevec_calcProbOfOutcome (Qureg qureg, const int measureQubit, int outcome)
 
qreal statevec_calcTotalProb (Qureg qureg)
 
void statevec_cloneQureg (Qureg targetQureg, Qureg copyQureg)
 works for both statevectors and density matrices More...
 
void statevec_collapseToKnownProbOutcome (Qureg qureg, const int measureQubit, int outcome, qreal outcomeProb)
 
void statevec_compactUnitary (Qureg qureg, const int targetQubit, Complex alpha, Complex beta)
 
int statevec_compareStates (Qureg mq1, Qureg mq2, qreal precision)
 
void statevec_controlledCompactUnitary (Qureg qureg, const int controlQubit, const int targetQubit, Complex alpha, Complex beta)
 
void statevec_controlledMultiQubitUnitary (Qureg qureg, int ctrl, int *targets, const int numTargets, ComplexMatrixN u)
 
void statevec_controlledNot (Qureg qureg, const int controlQubit, const int targetQubit)
 
void statevec_controlledPauliY (Qureg qureg, const int controlQubit, const int targetQubit)
 
void statevec_controlledPauliYConj (Qureg qureg, const int controlQubit, const int targetQubit)
 
void statevec_controlledPhaseFlip (Qureg qureg, const int idQubit1, const int idQubit2)
 
void statevec_controlledPhaseShift (Qureg qureg, const int idQubit1, const int idQubit2, qreal angle)
 
void statevec_controlledRotateAroundAxis (Qureg qureg, const int controlQubit, const int targetQubit, qreal angle, Vector axis)
 
void statevec_controlledRotateAroundAxisConj (Qureg qureg, const int controlQubit, const int targetQubit, qreal angle, Vector axis)
 
void statevec_controlledRotateX (Qureg qureg, const int controlQubit, const int targetQubit, qreal angle)
 
void statevec_controlledRotateY (Qureg qureg, const int controlQubit, const int targetQubit, qreal angle)
 
void statevec_controlledRotateZ (Qureg qureg, const int controlQubit, const int targetQubit, qreal angle)
 
void statevec_controlledTwoQubitUnitary (Qureg qureg, const int controlQubit, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
 
void statevec_controlledUnitary (Qureg qureg, const int controlQubit, const int targetQubit, ComplexMatrix2 u)
 
void statevec_createQureg (Qureg *qureg, int numQubits, QuESTEnv env)
 
void statevec_destroyQureg (Qureg qureg, QuESTEnv env)
 
qreal statevec_getImagAmp (Qureg qureg, long long int index)
 
qreal statevec_getProbAmp (Qureg qureg, long long int index)
 
qreal statevec_getRealAmp (Qureg qureg, long long int index)
 
void statevec_hadamard (Qureg qureg, const int targetQubit)
 
void statevec_initBlankState (Qureg qureg)
 
void statevec_initClassicalState (Qureg qureg, long long int stateInd)
 
void statevec_initDebugState (Qureg qureg)
 Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value. More...
 
void statevec_initPlusState (Qureg qureg)
 
int statevec_initStateFromSingleFile (Qureg *qureg, char filename[200], QuESTEnv env)
 
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 other qubits are in an equal superposition of zero and one. More...
 
void statevec_initZeroState (Qureg qureg)
 
int statevec_measureWithStats (Qureg qureg, int measureQubit, qreal *outcomeProb)
 
void statevec_multiControlledMultiQubitUnitary (Qureg qureg, long long int ctrlMask, int *targs, const int numTargs, ComplexMatrixN u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledPhaseFlip (Qureg qureg, int *controlQubits, int numControlQubits)
 
void statevec_multiControlledPhaseShift (Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
 
void statevec_multiControlledTwoQubitUnitary (Qureg qureg, long long int ctrlMask, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
 This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct. More...
 
void statevec_multiControlledUnitary (Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, const int targetQubit, ComplexMatrix2 u)
 
void statevec_multiQubitUnitary (Qureg qureg, int *targets, const int numTargets, ComplexMatrixN u)
 
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 More...
 
void statevec_multiRotateZ (Qureg qureg, long long int mask, qreal angle)
 
void statevec_pauliX (Qureg qureg, const int targetQubit)
 
void statevec_pauliY (Qureg qureg, const int targetQubit)
 
void statevec_pauliYConj (Qureg qureg, const int targetQubit)
 
void statevec_pauliZ (Qureg qureg, const int targetQubit)
 
void statevec_phaseShift (Qureg qureg, const int targetQubit, qreal angle)
 
void statevec_phaseShiftByTerm (Qureg qureg, const int targetQubit, Complex term)
 
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. More...
 
void statevec_rotateAroundAxis (Qureg qureg, const int rotQubit, qreal angle, Vector axis)
 
void statevec_rotateAroundAxisConj (Qureg qureg, const int rotQubit, qreal angle, Vector axis)
 
void statevec_rotateX (Qureg qureg, const int rotQubit, qreal angle)
 
void statevec_rotateY (Qureg qureg, const int rotQubit, qreal angle)
 
void statevec_rotateZ (Qureg qureg, const int rotQubit, qreal angle)
 
void statevec_setAmps (Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
 
void statevec_setWeightedQureg (Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
 
void statevec_sGate (Qureg qureg, const int targetQubit)
 
void statevec_sGateConj (Qureg qureg, const int targetQubit)
 
void statevec_sqrtSwapGate (Qureg qureg, int qb1, int qb2)
 
void statevec_sqrtSwapGateConj (Qureg qureg, int qb1, int qb2)
 
void statevec_swapQubitAmps (Qureg qureg, int qb1, int qb2)
 
void statevec_tGate (Qureg qureg, const int targetQubit)
 
void statevec_tGateConj (Qureg qureg, const int targetQubit)
 
void statevec_twoQubitUnitary (Qureg qureg, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
 
void statevec_unitary (Qureg qureg, const int targetQubit, ComplexMatrix2 u)
 

Detailed Description

General functions used internally, supplied by QuEST_common or by hardware-specific backends. Note that some bespoke functions used only internally exist in QuEST_qasm.h and QuEST_validation.h

Author
Ania Brown (statevecs, original architecture)
Tyson Jones (re-architecture, statevecs, density matrices)

Definition in file QuEST_internal.h.

Function Documentation

◆ conjugateMatrixN()

void conjugateMatrixN ( ComplexMatrixN  u)

◆ densmatr_calcFidelity()

qreal densmatr_calcFidelity ( Qureg  qureg,
Qureg  pureState 
)

Definition at line 415 of file QuEST_cpu_distributed.c.

415  {
416 
417  // set qureg's pairState is to be the full pureState (on every node)
418  copyVecIntoMatrixPairState(qureg, pureState);
419 
420  // collect calcFidelityLocal by every machine
421  qreal localSum = densmatr_calcFidelityLocal(qureg, pureState);
422 
423  // sum each localSum
424  qreal globalSum;
425  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
426 
427  return globalSum;
428 }

References copySharedReduceBlock(), copyVecIntoMatrixPairState(), densmatr_calcFidelityLocal(), Qureg::firstLevelReduction, Qureg::numQubitsRepresented, Qureg::pairStateVec, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, Qureg::stateVec, and swapDouble().

Referenced by calcFidelity().

◆ densmatr_calcHilbertSchmidtDistance()

qreal densmatr_calcHilbertSchmidtDistance ( Qureg  a,
Qureg  b 
)

Definition at line 430 of file QuEST_cpu_distributed.c.

430  {
431 
433 
434  qreal globalSum;
435  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
436 
437  qreal dist = sqrt(globalSum);
438  return dist;
439 }

References copySharedReduceBlock(), densmatr_calcHilbertSchmidtDistanceSquaredLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

Referenced by calcHilbertSchmidtDistance().

◆ densmatr_calcInnerProduct()

qreal densmatr_calcInnerProduct ( Qureg  a,
Qureg  b 
)

Definition at line 441 of file QuEST_cpu_distributed.c.

441  {
442 
443  qreal localSum = densmatr_calcInnerProductLocal(a, b);
444 
445  qreal globalSum;
446  MPI_Allreduce(&localSum, &globalSum, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
447 
448  qreal dist = globalSum;
449  return dist;
450 }

References copySharedReduceBlock(), densmatr_calcInnerProductLocal(), Qureg::firstLevelReduction, Qureg::numAmpsTotal, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

Referenced by calcDensityInnerProduct().

◆ densmatr_calcProbOfOutcome()

qreal densmatr_calcProbOfOutcome ( Qureg  qureg,
const int  measureQubit,
int  outcome 
)

Definition at line 1279 of file QuEST_cpu_distributed.c.

1279  {
1280 
1281  qreal zeroProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
1282 
1283  qreal outcomeProb;
1284  MPI_Allreduce(&zeroProb, &outcomeProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
1285  if (outcome == 1)
1286  outcomeProb = 1.0 - outcomeProb;
1287 
1288  return outcomeProb;
1289 }

References densmatr_findProbabilityOfZero(), densmatr_findProbabilityOfZeroLocal(), and qreal.

Referenced by calcProbOfOutcome(), collapseToOutcome(), and densmatr_measureWithStats().

◆ densmatr_calcPurity()

qreal densmatr_calcPurity ( Qureg  qureg)

Computes the trace of the density matrix squared.

Definition at line 1291 of file QuEST_cpu_distributed.c.

1291  {
1292 
1293  qreal localPurity = densmatr_calcPurityLocal(qureg);
1294 
1295  qreal globalPurity;
1296  MPI_Allreduce(&localPurity, &globalPurity, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
1297 
1298  return globalPurity;
1299 }

References copySharedReduceBlock(), densmatr_calcPurityLocal(), Qureg::deviceStateVec, Qureg::firstLevelReduction, Qureg::numAmpsPerChunk, qreal, REDUCE_SHARED_SIZE, Qureg::secondLevelReduction, and swapDouble().

Referenced by calcPurity().

◆ densmatr_calcTotalProb()

qreal densmatr_calcTotalProb ( Qureg  qureg)

Definition at line 53 of file QuEST_cpu_distributed.c.

53  {
54 
55  // computes the trace by summing every element ("diag") with global index (2^n + 1)i for i in [0, 2^n-1]
56 
57  // computes first local index containing a diagonal element
58  long long int diagSpacing = 1LL + (1LL << qureg.numQubitsRepresented);
59  long long int numPrevDiags = (qureg.chunkId>0)? 1+(qureg.chunkId*qureg.numAmpsPerChunk)/diagSpacing : 0;
60  long long int globalIndNextDiag = diagSpacing * numPrevDiags;
61  long long int localIndNextDiag = globalIndNextDiag % qureg.numAmpsPerChunk;
62  long long int index;
63 
64  qreal rankTotal = 0;
65  qreal y, t, c;
66  c = 0;
67 
68  // iterates every local diagonal
69  for (index=localIndNextDiag; index < qureg.numAmpsPerChunk; index += diagSpacing) {
70 
71  // Kahan summation - brackets are important
72  y = qureg.stateVec.real[index] - c;
73  t = rankTotal + y;
74  c = ( t - rankTotal ) - y;
75  rankTotal = t;
76  }
77 
78  // combine each node's sum of diagonals
79  qreal globalTotal;
80  if (qureg.numChunks > 1)
81  MPI_Allreduce(&rankTotal, &globalTotal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
82  else
83  globalTotal = rankTotal;
84 
85  return globalTotal;
86 }

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

Referenced by calcTotalProb(), and statevec_calcExpecPauliProd().

◆ densmatr_collapseToKnownProbOutcome()

void densmatr_collapseToKnownProbOutcome ( Qureg  qureg,
const int  measureQubit,
int  outcome,
qreal  outcomeProb 
)

Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.

Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.

Definition at line 784 of file QuEST_cpu.c.

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

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

Referenced by collapseToOutcome(), and densmatr_measureWithStats().

◆ densmatr_initClassicalState()

void densmatr_initClassicalState ( Qureg  qureg,
long long int  stateInd 
)

Definition at line 1114 of file QuEST_cpu.c.

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

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

Referenced by initClassicalState().

◆ densmatr_initPlusState()

void densmatr_initPlusState ( Qureg  targetQureg)

Definition at line 1153 of file QuEST_cpu.c.

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

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

Referenced by initPlusState().

◆ densmatr_initPureState()

void densmatr_initPureState ( Qureg  targetQureg,
Qureg  copyQureg 
)

Definition at line 452 of file QuEST_cpu_distributed.c.

452  {
453 
454  if (targetQureg.numChunks==1){
455  // local version
456  // save pointers to qureg's pair state
457  qreal* quregPairRePtr = targetQureg.pairStateVec.real;
458  qreal* quregPairImPtr = targetQureg.pairStateVec.imag;
459 
460  // populate qureg pair state with pure state (by repointing)
461  targetQureg.pairStateVec.real = copyQureg.stateVec.real;
462  targetQureg.pairStateVec.imag = copyQureg.stateVec.imag;
463 
464  // populate density matrix via it's pairState
465  densmatr_initPureStateLocal(targetQureg, copyQureg);
466 
467  // restore pointers
468  targetQureg.pairStateVec.real = quregPairRePtr;
469  targetQureg.pairStateVec.imag = quregPairImPtr;
470  } else {
471  // set qureg's pairState is to be the full pure state (on every node)
472  copyVecIntoMatrixPairState(targetQureg, copyQureg);
473 
474  // update every density matrix chunk using pairState
475  densmatr_initPureStateLocal(targetQureg, copyQureg);
476  }
477 }

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

Referenced by initPureState().

◆ densmatr_measureWithStats()

int densmatr_measureWithStats ( Qureg  qureg,
int  measureQubit,
qreal outcomeProb 
)

Definition at line 368 of file QuEST_common.c.

368  {
369 
370  qreal zeroProb = densmatr_calcProbOfOutcome(qureg, measureQubit, 0);
371  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
372  densmatr_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
373  return outcome;
374 }

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

Referenced by measure(), and measureWithStats().

◆ densmatr_mixDamping()

void densmatr_mixDamping ( Qureg  qureg,
const int  targetQubit,
qreal  damping 
)

Definition at line 727 of file QuEST_cpu_distributed.c.

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

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().

◆ densmatr_mixDensityMatrix()

void densmatr_mixDensityMatrix ( Qureg  combineQureg,
qreal  otherProb,
Qureg  otherQureg 
)

Definition at line 889 of file QuEST_cpu.c.

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

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

Referenced by mixDensityMatrix().

◆ densmatr_mixDephasing()

void densmatr_mixDephasing ( Qureg  qureg,
const int  targetQubit,
qreal  dephase 
)

Definition at line 79 of file QuEST_cpu.c.

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

References densmatr_oneQubitDegradeOffDiagonal(), and qreal.

Referenced by densmatr_mixDepolarising(), densmatr_mixDepolarisingDistributed(), and mixDephasing().

◆ densmatr_mixDepolarising()

void densmatr_mixDepolarising ( Qureg  qureg,
const int  targetQubit,
qreal  depolLevel 
)

Definition at line 700 of file QuEST_cpu_distributed.c.

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

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().

◆ densmatr_mixKrausMap()

void densmatr_mixKrausMap ( Qureg  qureg,
int  target,
ComplexMatrix2 ops,
int  numOps 
)

Definition at line 599 of file QuEST_common.c.

599  {
600 
601  ComplexMatrix4 superOp;
602  populateKrausSuperOperator2(&superOp, ops, numOps);
603  densmatr_applyKrausSuperoperator(qureg, target, superOp);
604 }

References densmatr_applyKrausSuperoperator(), and populateKrausSuperOperator2().

Referenced by densmatr_mixPauli(), and mixKrausMap().

◆ densmatr_mixMultiQubitKrausMap()

void densmatr_mixMultiQubitKrausMap ( Qureg  qureg,
int *  targets,
int  numTargets,
ComplexMatrixN ops,
int  numOps 
)

Definition at line 642 of file QuEST_common.c.

642  {
643 
644  ComplexMatrixN superOp;
645 
646  /* superOp will contain 2^(4 numTargets) complex numbers.
647  * At double precision, superOp will cost additional memory:
648  * numTargs=1 -> 0.25 KiB
649  * numTargs=2 -> 4 KiB
650  * numTargs=3 -> 64 KiB
651  * numTargs=4 -> 1 MiB
652  * numTargs=5 -> 16 MiB.
653  * At quad precision (usually 10 B per number, but possibly 16 B due to alignment),
654  * this costs at most double.
655  *
656  * Hence, if superOp is kept in the stack, numTargs >= 4 would exceed Windows' 1 MB
657  * maximum stack-space allocation (numTargs >= 5 exceeding Linux' 8 MB). Therefore,
658  * for numTargets < 4, superOp will be kept in the stack, else in the heap
659  */
660 
661  if (numTargets < 4) {
662  // everything must live in 'if' since this macro declares local vars
663  macro_allocStackComplexMatrixN(superOp, 2*numTargets);
664  populateKrausSuperOperatorN(&superOp, ops, numOps);
665  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
666  }
667  else {
668  superOp = createComplexMatrixN(2*numTargets);
669  populateKrausSuperOperatorN(&superOp, ops, numOps);
670  densmatr_applyMultiQubitKrausSuperoperator(qureg, targets, numTargets, superOp);
671  destroyComplexMatrixN(superOp);
672  }
673 }

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

Referenced by mixMultiQubitKrausMap().

◆ densmatr_mixPauli()

void densmatr_mixPauli ( Qureg  qureg,
int  qubit,
qreal  pX,
qreal  pY,
qreal  pZ 
)

Definition at line 675 of file QuEST_common.c.

675  {
676 
677  // convert pauli probabilities into Kraus map
678  const int numOps = 4;
679  ComplexMatrix2 ops[numOps];
680  for (int n=0; n < numOps; n++)
681  ops[n] = (ComplexMatrix2) {.real={{0}}, .imag={{0}}};
682 
683  qreal facs[4] = { // literal numOps=4 for valid initialisation
684  sqrt(1-(probX + probY + probZ)),
685  sqrt(probX),
686  sqrt(probY),
687  sqrt(probZ)
688  };
689  ops[0].real[0][0] = facs[0]; ops[0].real[1][1] = facs[0];
690  ops[1].real[0][1] = facs[1]; ops[1].real[1][0] = facs[1];
691  ops[2].imag[0][1] = -facs[2]; ops[2].imag[1][0] = facs[2];
692  ops[3].real[0][0] = facs[3]; ops[3].real[1][1] = -facs[3];
693 
694  densmatr_mixKrausMap(qureg, qubit, ops, numOps);
695 }

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

Referenced by mixPauli().

◆ densmatr_mixTwoQubitDephasing()

void densmatr_mixTwoQubitDephasing ( Qureg  qureg,
const int  qubit1,
const int  qubit2,
qreal  dephase 
)

Definition at line 84 of file QuEST_cpu.c.

84  {
85  qreal retain=1-dephase;
86 
87  const 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) \
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 }

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

Referenced by densmatr_mixTwoQubitDepolarising(), and mixTwoQubitDephasing().

◆ densmatr_mixTwoQubitDepolarising()

void densmatr_mixTwoQubitDepolarising ( Qureg  qureg,
int  qubit1,
int  qubit2,
qreal  depolLevel 
)

Definition at line 754 of file QuEST_cpu_distributed.c.

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

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().

◆ densmatr_mixTwoQubitKrausMap()

void densmatr_mixTwoQubitKrausMap ( Qureg  qureg,
int  target1,
int  target2,
ComplexMatrix4 ops,
int  numOps 
)

Definition at line 634 of file QuEST_common.c.

634  {
635 
636  ComplexMatrixN superOp;
637  macro_allocStackComplexMatrixN(superOp, 4);
638  populateKrausSuperOperator4(&superOp, ops, numOps);
639  densmatr_applyTwoQubitKrausSuperoperator(qureg, target1, target2, superOp);
640 }

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

Referenced by mixTwoQubitKrausMap().

◆ ensureIndsIncrease()

void ensureIndsIncrease ( int *  ind1,
int *  ind2 
)

Definition at line 63 of file QuEST_common.c.

63  {
64 
65  if (*ind1 > *ind2) {
66  int copy = *ind1;
67  *ind1 = *ind2;
68  *ind2 = copy;
69  }
70 }

Referenced by mixTwoQubitDephasing(), and mixTwoQubitDepolarising().

◆ getComplexPairAndPhaseFromUnitary()

void getComplexPairAndPhaseFromUnitary ( ComplexMatrix2  u,
Complex alpha,
Complex beta,
qreal globalPhase 
)

maps U(r0c0, r0c1, r1c0, r1c1) to exp(i globalPhase) U(alpha, beta)

Definition at line 135 of file QuEST_common.c.

135  {
136 
137  qreal r0c0Phase = atan2(u.imag[0][0], u.real[0][0]);
138  qreal r1c1Phase = atan2(u.imag[1][1], u.real[1][1]);
139  *globalPhase = (r0c0Phase + r1c1Phase)/2.0;
140 
141  qreal cosPhase = cos(*globalPhase);
142  qreal sinPhase = sin(*globalPhase);
143  alpha->real = u.real[0][0]*cosPhase + u.imag[0][0]*sinPhase;
144  alpha->imag = u.imag[0][0]*cosPhase - u.real[0][0]*sinPhase;
145  beta->real = u.real[1][0]*cosPhase + u.imag[1][0]*sinPhase;
146  beta->imag = u.imag[1][0]*cosPhase - u.real[1][0]*sinPhase;
147 }

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

Referenced by qasm_recordControlledUnitary(), qasm_recordMultiControlledUnitary(), and qasm_recordUnitary().

◆ getComplexPairFromRotation()

void getComplexPairFromRotation ( qreal  angle,
Vector  axis,
Complex alpha,
Complex beta 
)

Definition at line 113 of file QuEST_common.c.

113  {
114 
115  Vector unitAxis = getUnitVector(axis);
116  alpha->real = cos(angle/2.0);
117  alpha->imag = - sin(angle/2.0)*unitAxis.z;
118  beta->real = sin(angle/2.0)*unitAxis.y;
119  beta->imag = - sin(angle/2.0)*unitAxis.x;
120 }

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().

◆ getConjugateMatrix2()

ComplexMatrix2 getConjugateMatrix2 ( ComplexMatrix2  src)

Definition at line 98 of file QuEST_common.c.

98  {
99  ComplexMatrix2 conj;
100  macro_setConjugateMatrix(conj, src, 2);
101  return conj;
102 }

References macro_setConjugateMatrix.

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

◆ getConjugateMatrix4()

ComplexMatrix4 getConjugateMatrix4 ( ComplexMatrix4  src)

Definition at line 103 of file QuEST_common.c.

103  {
104  ComplexMatrix4 conj;
105  macro_setConjugateMatrix(conj, src, 4);
106  return conj;
107 }

References macro_setConjugateMatrix.

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

◆ getConjugateScalar()

Complex getConjugateScalar ( Complex  scalar)

Definition at line 84 of file QuEST_common.c.

84  {
85 
86  Complex conjScalar;
87  conjScalar.real = scalar.real;
88  conjScalar.imag = - scalar.imag;
89  return conjScalar;
90 }

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

Referenced by compactUnitary(), and controlledCompactUnitary().

◆ getControlFlipMask()

long long int getControlFlipMask ( int *  controlQubits,
int *  controlState,
const int  numControlQubits 
)

Definition at line 53 of file QuEST_common.c.

53  {
54 
55  long long int mask=0;
56  for (int i=0; i<numControlQubits; i++)
57  if (controlState[i] == 0)
58  mask = mask | (1LL << controlQubits[i]);
59 
60  return mask;
61 }

Referenced by multiStateControlledUnitary().

◆ getQubitBitMask()

long long int getQubitBitMask ( int *  controlQubits,
const int  numControlQubits 
)

◆ getQuESTDefaultSeedKey()

void getQuESTDefaultSeedKey ( unsigned long int *  key)

Definition at line 181 of file QuEST_common.c.

181  {
182  // init MT random number generator with two keys -- time and pid
183  // for the MPI version, it is ok that all procs will get the same seed as random numbers will only be
184  // used by the master process
185 #if defined(_WIN32) && ! defined(__MINGW32__)
186 
187  unsigned long int pid = (unsigned long int) _getpid();
188  unsigned long int msecs = (unsigned long int) GetTickCount64();
189 
190  key[0] = msecs; key[1] = pid;
191 #else
192  struct timeval tv;
193  gettimeofday(&tv, NULL);
194 
195  double time_in_mill =
196  (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond
197 
198  unsigned long int pid = getpid();
199  unsigned long int msecs = (unsigned long int) time_in_mill;
200 
201  key[0] = msecs; key[1] = pid;
202 #endif
203 }

Referenced by seedQuESTDefault().

◆ getVectorMagnitude()

qreal getVectorMagnitude ( Vector  vec)

Definition at line 72 of file QuEST_common.c.

72  {
73 
74  return sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
75 }

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

Referenced by getUnitVector(), and validateVector().

◆ getZYZRotAnglesFromComplexPair()

void getZYZRotAnglesFromComplexPair ( Complex  alpha,
Complex  beta,
qreal rz2,
qreal ry,
qreal rz1 
)

maps U(alpha, beta) to Rz(rz2) Ry(ry) Rz(rz1)

Definition at line 123 of file QuEST_common.c.

123  {
124 
125  qreal alphaMag = sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag);
126  *ry = 2.0 * acos(alphaMag);
127 
128  qreal alphaPhase = atan2(alpha.imag, alpha.real);
129  qreal betaPhase = atan2(beta.imag, beta.real);
130  *rz2 = - alphaPhase + betaPhase;
131  *rz1 = - alphaPhase - betaPhase;
132 }

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

Referenced by qasm_recordAxisRotation(), qasm_recordCompactUnitary(), qasm_recordControlledAxisRotation(), qasm_recordControlledCompactUnitary(), qasm_recordControlledUnitary(), qasm_recordMultiControlledUnitary(), and qasm_recordUnitary().

◆ hashString()

unsigned long int hashString ( char *  str)

Definition at line 171 of file QuEST_common.c.

171  {
172  unsigned long int hash = 5381;
173  int c;
174 
175  while ((c = *str++))
176  hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
177 
178  return hash;
179 }

◆ setConjugateMatrixN()

void setConjugateMatrixN ( ComplexMatrixN  m)

Definition at line 108 of file QuEST_common.c.

108  {
109  int len = 1 << m.numQubits;
110  macro_setConjugateMatrix(m, m, len);
111 }

References macro_setConjugateMatrix, and ComplexMatrixN::numQubits.

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

◆ shiftIndices()

void shiftIndices ( int *  indices,
int  numIndices,
int  shift 
)

Definition at line 149 of file QuEST_common.c.

149  {
150  for (int j=0; j < numIndices; j++)
151  indices[j] += shift;
152 }

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

◆ statevec_applyPauliSum()

void statevec_applyPauliSum ( Qureg  inQureg,
enum pauliOpType allCodes,
qreal termCoeffs,
int  numSumTerms,
Qureg  outQureg 
)

Definition at line 493 of file QuEST_common.c.

493  {
494 
495  int numQb = inQureg.numQubitsRepresented;
496  int targs[numQb];
497  for (int q=0; q < numQb; q++)
498  targs[q] = q;
499 
500  statevec_initBlankState(outQureg);
501 
502  for (int t=0; t < numSumTerms; t++) {
503  Complex coef = (Complex) {.real=termCoeffs[t], .imag=0};
504  Complex iden = (Complex) {.real=1, .imag=0};
505  Complex zero = (Complex) {.real=0, .imag=0};
506 
507  // outQureg += coef paulis(inQureg)
508  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
509  statevec_setWeightedQureg(coef, inQureg, iden, outQureg, zero, outQureg);
510 
511  // undero paulis(inQureg), exploiting XX=YY=ZZ=I
512  statevec_applyPauliProd(inQureg, targs, &allCodes[t*numQb], numQb);
513  }
514 }

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

Referenced by applyPauliSum().

◆ statevec_calcExpecPauliProd()

qreal statevec_calcExpecPauliProd ( Qureg  qureg,
int *  targetQubits,
enum pauliOpType pauliCodes,
int  numTargets,
Qureg  workspace 
)

Definition at line 464 of file QuEST_common.c.

464  {
465 
466  statevec_cloneQureg(workspace, qureg);
467  statevec_applyPauliProd(workspace, targetQubits, pauliCodes, numTargets);
468 
469  // compute the expected value
470  qreal value;
471  if (qureg.isDensityMatrix)
472  value = densmatr_calcTotalProb(workspace); // Trace(ops qureg)
473  else
474  value = statevec_calcInnerProduct(workspace, qureg).real; // <qureg|ops|qureg>
475 
476  return value;
477 }

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

Referenced by calcExpecPauliProd(), and statevec_calcExpecPauliSum().

◆ statevec_calcExpecPauliSum()

qreal statevec_calcExpecPauliSum ( Qureg  qureg,
enum pauliOpType allCodes,
qreal termCoeffs,
int  numSumTerms,
Qureg  workspace 
)

Definition at line 479 of file QuEST_common.c.

479  {
480 
481  int numQb = qureg.numQubitsRepresented;
482  int targs[numQb];
483  for (int q=0; q < numQb; q++)
484  targs[q] = q;
485 
486  qreal value = 0;
487  for (int t=0; t < numSumTerms; t++)
488  value += termCoeffs[t] * statevec_calcExpecPauliProd(qureg, targs, &allCodes[t*numQb], numQb, workspace);
489 
490  return value;
491 }

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

Referenced by calcExpecPauliSum().

◆ statevec_calcFidelity()

qreal statevec_calcFidelity ( Qureg  qureg,
Qureg  pureState 
)

Definition at line 376 of file QuEST_common.c.

376  {
377 
378  Complex innerProd = statevec_calcInnerProduct(qureg, pureState);
379  qreal innerProdMag = innerProd.real*innerProd.real + innerProd.imag*innerProd.imag;
380  return innerProdMag;
381 }

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

Referenced by calcFidelity().

◆ statevec_calcInnerProduct()

Complex statevec_calcInnerProduct ( Qureg  bra,
Qureg  ket 
)

Terrible code which unnecessarily individually computes and sums the real and imaginary components of the inner product, so as to not have to worry about keeping the sums separated during reduction.

Truly disgusting, probably doubles runtime, please fix. @TODO could even do the kernel twice, storing real in bra.reduc and imag in ket.reduc?

Definition at line 35 of file QuEST_cpu_distributed.c.

35  {
36 
37  Complex localInnerProd = statevec_calcInnerProductLocal(bra, ket);
38  if (bra.numChunks == 1)
39  return localInnerProd;
40 
41  qreal localReal = localInnerProd.real;
42  qreal localImag = localInnerProd.imag;
43  qreal globalReal, globalImag;
44  MPI_Allreduce(&localReal, &globalReal, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
45  MPI_Allreduce(&localImag, &globalImag, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
46 
47  Complex globalInnerProd;
48  globalInnerProd.real = globalReal;
49  globalInnerProd.imag = globalImag;
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().

Referenced by calcInnerProduct(), statevec_calcExpecPauliProd(), and statevec_calcFidelity().

◆ statevec_calcProbOfOutcome()

qreal statevec_calcProbOfOutcome ( Qureg  qureg,
const int  measureQubit,
int  outcome 
)

Definition at line 1263 of file QuEST_cpu_distributed.c.

1264 {
1265  qreal stateProb=0, totalStateProb=0;
1266  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
1267  if (skipValuesWithinRank) {
1268  stateProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
1269  } else {
1270  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
1271  stateProb = statevec_findProbabilityOfZeroDistributed(qureg);
1272  } else stateProb = 0;
1273  }
1274  MPI_Allreduce(&stateProb, &totalStateProb, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
1275  if (outcome==1) totalStateProb = 1.0 - totalStateProb;
1276  return totalStateProb;
1277 }

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

Referenced by calcProbOfOutcome(), collapseToOutcome(), and statevec_measureWithStats().

◆ statevec_calcTotalProb()

qreal statevec_calcTotalProb ( Qureg  qureg)

Definition at line 88 of file QuEST_cpu_distributed.c.

88  {
89  // Implemented using Kahan summation for greater accuracy at a slight floating
90  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
91  qreal pTotal=0;
92  qreal y, t, c;
93  qreal allRankTotals=0;
94  long long int index;
95  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
96  c = 0.0;
97  for (index=0; index<numAmpsPerRank; index++){
98  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
99  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
100  t = pTotal + y;
101  // Don't change the bracketing on the following line
102  c = ( t - pTotal ) - y;
103  pTotal = t;
104  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
105  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
106  t = pTotal + y;
107  // Don't change the bracketing on the following line
108  c = ( t - pTotal ) - y;
109  pTotal = t;
110  }
111  if (qureg.numChunks>1)
112  MPI_Allreduce(&pTotal, &allRankTotals, 1, MPI_QuEST_REAL, MPI_SUM, MPI_COMM_WORLD);
113  else
114  allRankTotals=pTotal;
115 
116  return allRankTotals;
117 }

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

Referenced by calcTotalProb().

◆ statevec_cloneQureg()

void statevec_cloneQureg ( Qureg  targetQureg,
Qureg  copyQureg 
)

works for both statevectors and density matrices

Definition at line 1474 of file QuEST_cpu.c.

1474  {
1475 
1476  // registers are equal sized, so nodes hold the same state-vector partitions
1477  long long int stateVecSize;
1478  long long int index;
1479 
1480  // dimension of the state vector
1481  stateVecSize = targetQureg.numAmpsPerChunk;
1482 
1483  // Can't use qureg->stateVec as a private OMP var
1484  qreal *targetStateVecReal = targetQureg.stateVec.real;
1485  qreal *targetStateVecImag = targetQureg.stateVec.imag;
1486  qreal *copyStateVecReal = copyQureg.stateVec.real;
1487  qreal *copyStateVecImag = copyQureg.stateVec.imag;
1488 
1489  // initialise the state to |0000..0000>
1490 # ifdef _OPENMP
1491 # pragma omp parallel \
1492  default (none) \
1493  shared (stateVecSize, targetStateVecReal, targetStateVecImag, copyStateVecReal, copyStateVecImag) \
1494  private (index)
1495 # endif
1496  {
1497 # ifdef _OPENMP
1498 # pragma omp for schedule (static)
1499 # endif
1500  for (index=0; index<stateVecSize; index++) {
1501  targetStateVecReal[index] = copyStateVecReal[index];
1502  targetStateVecImag[index] = copyStateVecImag[index];
1503  }
1504  }
1505 }

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

Referenced by cloneQureg(), createCloneQureg(), initPureState(), and statevec_calcExpecPauliProd().

◆ statevec_collapseToKnownProbOutcome()

void statevec_collapseToKnownProbOutcome ( Qureg  qureg,
const int  measureQubit,
int  outcome,
qreal  outcomeProb 
)

Definition at line 1301 of file QuEST_cpu_distributed.c.

1302 {
1303  int skipValuesWithinRank = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, measureQubit);
1304  if (skipValuesWithinRank) {
1305  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, totalStateProb);
1306  } else {
1307  if (!isChunkToSkipInFindPZero(qureg.chunkId, qureg.numAmpsPerChunk, measureQubit)){
1308  // chunk has amps for q=0
1309  if (outcome==0) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
1310  totalStateProb);
1312  } else {
1313  // chunk has amps for q=1
1314  if (outcome==1) statevec_collapseToKnownProbOutcomeDistributedRenorm(qureg, measureQubit,
1315  totalStateProb);
1317  }
1318  }
1319 }

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

Referenced by collapseToOutcome(), and statevec_measureWithStats().

◆ statevec_compactUnitary()

void statevec_compactUnitary ( Qureg  qureg,
const int  targetQubit,
Complex  alpha,
Complex  beta 
)

Definition at line 846 of file QuEST_cpu_distributed.c.

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

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().

◆ statevec_compareStates()

int statevec_compareStates ( Qureg  mq1,
Qureg  mq2,
qreal  precision 
)

Definition at line 1643 of file QuEST_cpu.c.

1643  {
1644  qreal diff;
1645  long long int chunkSize = mq1.numAmpsPerChunk;
1646 
1647  for (long long int i=0; i<chunkSize; i++){
1648  diff = absReal(mq1.stateVec.real[i] - mq2.stateVec.real[i]);
1649  if (diff>precision) return 0;
1650  diff = absReal(mq1.stateVec.imag[i] - mq2.stateVec.imag[i]);
1651  if (diff>precision) return 0;
1652  }
1653  return 1;
1654 }

References copyStateFromGPU(), Qureg::numAmpsPerChunk, qreal, and Qureg::stateVec.

Referenced by compareStates().

◆ statevec_controlledCompactUnitary()

void statevec_controlledCompactUnitary ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
Complex  alpha,
Complex  beta 
)

Definition at line 922 of file QuEST_cpu_distributed.c.

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

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().

◆ statevec_controlledMultiQubitUnitary()

void statevec_controlledMultiQubitUnitary ( Qureg  qureg,
int  ctrl,
int *  targets,
const int  numTargets,
ComplexMatrixN  u 
)

Definition at line 534 of file QuEST_common.c.

534  {
535 
536  long long int ctrlMask = 1LL << ctrl;
537  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
538 }

References statevec_multiControlledMultiQubitUnitary().

Referenced by controlledMultiQubitUnitary().

◆ statevec_controlledNot()

void statevec_controlledNot ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit 
)

Definition at line 1063 of file QuEST_cpu_distributed.c.

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

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

Referenced by controlledNot().

◆ statevec_controlledPauliY()

void statevec_controlledPauliY ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit 
)

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  // all values required to update state vector lie in this rank
1153  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
1154  } else {
1155  // need to get corresponding chunk of state vector from other rank
1156  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1157  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1158  // get corresponding values from my pair
1159  exchangeStateVectors(qureg, pairRank);
1160  // this rank's values are either in the upper of lower half of the block
1161  if (rankIsUpper){
1162  statevec_controlledPauliYDistributed(qureg,controlQubit,
1163  qureg.pairStateVec, //in
1164  qureg.stateVec,
1165  conjFac); //out
1166  } else {
1167  statevec_controlledPauliYDistributed(qureg,controlQubit,
1168  qureg.pairStateVec, //in
1169  qureg.stateVec,
1170  -conjFac); //out
1171  }
1172  }
1173 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

Referenced by controlledPauliY().

◆ statevec_controlledPauliYConj()

void statevec_controlledPauliYConj ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit 
)

Definition at line 1175 of file QuEST_cpu_distributed.c.

1176 {
1177  int conjFac = -1;
1178 
1179  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
1180  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1181  int rankIsUpper; // rank's chunk is in upper half of block
1182  int pairRank; // rank of corresponding chunk
1183 
1184  if (useLocalDataOnly){
1185  // all values required to update state vector lie in this rank
1186  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
1187  } else {
1188  // need to get corresponding chunk of state vector from other rank
1189  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1190  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1191  // get corresponding values from my pair
1192  exchangeStateVectors(qureg, pairRank);
1193  // this rank's values are either in the upper of lower half of the block
1194  if (rankIsUpper){
1195  statevec_controlledPauliYDistributed(qureg,controlQubit,
1196  qureg.pairStateVec, //in
1197  qureg.stateVec,
1198  conjFac); //out
1199  } else {
1200  statevec_controlledPauliYDistributed(qureg,controlQubit,
1201  qureg.pairStateVec, //in
1202  qureg.stateVec,
1203  -conjFac); //out
1204  }
1205  }
1206 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledPauliYDistributed(), and statevec_controlledPauliYLocal().

Referenced by controlledPauliY().

◆ statevec_controlledPhaseFlip()

void statevec_controlledPhaseFlip ( Qureg  qureg,
const int  idQubit1,
const int  idQubit2 
)

Definition at line 3260 of file QuEST_cpu.c.

3261 {
3262  long long int index;
3263  long long int stateVecSize;
3264  int bit1, bit2;
3265 
3266  const long long int chunkSize=qureg.numAmpsPerChunk;
3267  const long long int chunkId=qureg.chunkId;
3268 
3269  // dimension of the state vector
3270  stateVecSize = qureg.numAmpsPerChunk;
3271  qreal *stateVecReal = qureg.stateVec.real;
3272  qreal *stateVecImag = qureg.stateVec.imag;
3273 
3274 # ifdef _OPENMP
3275 # pragma omp parallel for \
3276  default (none) \
3277  shared (stateVecSize, stateVecReal,stateVecImag ) \
3278  private (index,bit1,bit2) \
3279  schedule (static)
3280 # endif
3281  for (index=0; index<stateVecSize; index++) {
3282  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
3283  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
3284  if (bit1 && bit2) {
3285  stateVecReal [index] = - stateVecReal [index];
3286  stateVecImag [index] = - stateVecImag [index];
3287  }
3288  }
3289 }

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

Referenced by controlledPhaseFlip().

◆ statevec_controlledPhaseShift()

void statevec_controlledPhaseShift ( Qureg  qureg,
const int  idQubit1,
const int  idQubit2,
qreal  angle 
)

Definition at line 2980 of file QuEST_cpu.c.

2981 {
2982  long long int index;
2983  long long int stateVecSize;
2984  int bit1, bit2;
2985 
2986  const long long int chunkSize=qureg.numAmpsPerChunk;
2987  const long long int chunkId=qureg.chunkId;
2988 
2989  // dimension of the state vector
2990  stateVecSize = qureg.numAmpsPerChunk;
2991  qreal *stateVecReal = qureg.stateVec.real;
2992  qreal *stateVecImag = qureg.stateVec.imag;
2993 
2994  qreal stateRealLo, stateImagLo;
2995  const qreal cosAngle = cos(angle);
2996  const qreal sinAngle = sin(angle);
2997 
2998 # ifdef _OPENMP
2999 # pragma omp parallel for \
3000  default (none) \
3001  shared (stateVecSize, stateVecReal,stateVecImag ) \
3002  private (index,bit1,bit2,stateRealLo,stateImagLo) \
3003  schedule (static)
3004 # endif
3005  for (index=0; index<stateVecSize; index++) {
3006  bit1 = extractBit (idQubit1, index+chunkId*chunkSize);
3007  bit2 = extractBit (idQubit2, index+chunkId*chunkSize);
3008  if (bit1 && bit2) {
3009 
3010  stateRealLo = stateVecReal[index];
3011  stateImagLo = stateVecImag[index];
3012 
3013  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
3014  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
3015  }
3016  }
3017 }

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

Referenced by controlledPhaseShift().

◆ statevec_controlledRotateAroundAxis()

void statevec_controlledRotateAroundAxis ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
qreal  angle,
Vector  axis 
)

Definition at line 326 of file QuEST_common.c.

326  {
327 
328  Complex alpha, beta;
329  getComplexPairFromRotation(angle, axis, &alpha, &beta);
330  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
331 }

References getComplexPairFromRotation(), and statevec_controlledCompactUnitary().

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

◆ statevec_controlledRotateAroundAxisConj()

void statevec_controlledRotateAroundAxisConj ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
qreal  angle,
Vector  axis 
)

Definition at line 333 of file QuEST_common.c.

333  {
334 
335  Complex alpha, beta;
336  getComplexPairFromRotation(angle, axis, &alpha, &beta);
337  alpha.imag *= -1;
338  beta.imag *= -1;
339  statevec_controlledCompactUnitary(qureg, controlQubit, targetQubit, alpha, beta);
340 }

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

Referenced by controlledRotateAroundAxis().

◆ statevec_controlledRotateX()

void statevec_controlledRotateX ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
qreal  angle 
)

Definition at line 342 of file QuEST_common.c.

342  {
343 
344  Vector unitAxis = {1, 0, 0};
345  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
346 }

References statevec_controlledRotateAroundAxis().

Referenced by controlledRotateX().

◆ statevec_controlledRotateY()

void statevec_controlledRotateY ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
qreal  angle 
)

Definition at line 348 of file QuEST_common.c.

348  {
349 
350  Vector unitAxis = {0, 1, 0};
351  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
352 }

References statevec_controlledRotateAroundAxis().

Referenced by controlledRotateY().

◆ statevec_controlledRotateZ()

void statevec_controlledRotateZ ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
qreal  angle 
)

Definition at line 354 of file QuEST_common.c.

354  {
355 
356  Vector unitAxis = {0, 0, 1};
357  statevec_controlledRotateAroundAxis(qureg, controlQubit, targetQubit, angle, unitAxis);
358 }

References statevec_controlledRotateAroundAxis().

Referenced by controlledRotateZ().

◆ statevec_controlledTwoQubitUnitary()

void statevec_controlledTwoQubitUnitary ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit1,
const int  targetQubit2,
ComplexMatrix4  u 
)

Definition at line 522 of file QuEST_common.c.

522  {
523 
524  long long int ctrlMask = 1LL << controlQubit;
525  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
526 }

References statevec_multiControlledTwoQubitUnitary().

Referenced by controlledTwoQubitUnitary().

◆ statevec_controlledUnitary()

void statevec_controlledUnitary ( Qureg  qureg,
const int  controlQubit,
const int  targetQubit,
ComplexMatrix2  u 
)

Definition at line 960 of file QuEST_cpu_distributed.c.

962 {
963  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
964  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
965  Complex rot1, rot2;
966 
967  // rank's chunk is in upper half of block
968  int rankIsUpper;
969  int pairRank; // rank of corresponding chunk
970 
971  if (useLocalDataOnly){
972  // all values required to update state vector lie in this rank
973  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
974  } else {
975  // need to get corresponding chunk of state vector from other rank
976  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
977  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
978  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
979  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
980  // get corresponding values from my pair
981  exchangeStateVectors(qureg, pairRank);
982 
983  // this rank's values are either in the upper of lower half of the block. send values to controlledUnitaryDistributed
984  // in the correct order
985  if (rankIsUpper){
986  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
987  qureg.stateVec, //upper
988  qureg.pairStateVec, //lower
989  qureg.stateVec); //output
990  } else {
991  statevec_controlledUnitaryDistributed(qureg,controlQubit,rot1,rot2,
992  qureg.pairStateVec, //upper
993  qureg.stateVec, //lower
994  qureg.stateVec); //output
995  }
996  }
997 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_controlledUnitaryDistributed(), and statevec_controlledUnitaryLocal().

Referenced by controlledUnitary().

◆ statevec_createQureg()

void statevec_createQureg ( Qureg qureg,
int  numQubits,
QuESTEnv  env 
)

Definition at line 1278 of file QuEST_cpu.c.

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

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().

◆ statevec_destroyQureg()

void statevec_destroyQureg ( Qureg  qureg,
QuESTEnv  env 
)

Definition at line 1316 of file QuEST_cpu.c.

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

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

Referenced by destroyQureg().

◆ statevec_getImagAmp()

qreal statevec_getImagAmp ( Qureg  qureg,
long long int  index 
)

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.imag[index-chunkId*qureg.numAmpsPerChunk];
213  }
214  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
215  return el;
216 }

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

Referenced by getAmp(), getDensityAmp(), getImagAmp(), and statevec_getProbAmp().

◆ statevec_getProbAmp()

qreal statevec_getProbAmp ( Qureg  qureg,
long long int  index 
)

Definition at line 244 of file QuEST_common.c.

244  {
245  qreal real = statevec_getRealAmp(qureg, index);
246  qreal imag = statevec_getImagAmp(qureg, index);
247  return real*real + imag*imag;
248 }

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

Referenced by getProbAmp().

◆ statevec_getRealAmp()

qreal statevec_getRealAmp ( Qureg  qureg,
long long int  index 
)

Definition at line 198 of file QuEST_cpu_distributed.c.

198  {
199  int chunkId = getChunkIdFromIndex(qureg, index);
200  qreal el;
201  if (qureg.chunkId==chunkId){
202  el = qureg.stateVec.real[index-chunkId*qureg.numAmpsPerChunk];
203  }
204  MPI_Bcast(&el, 1, MPI_QuEST_REAL, chunkId, MPI_COMM_WORLD);
205  return el;
206 }

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

Referenced by getAmp(), getDensityAmp(), getRealAmp(), and statevec_getProbAmp().

◆ statevec_hadamard()

void statevec_hadamard ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 1208 of file QuEST_cpu_distributed.c.

1209 {
1210  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
1211  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1212 
1213  // rank's chunk is in upper half of block
1214  int rankIsUpper;
1215  int pairRank; // rank of corresponding chunk
1216 
1217  if (useLocalDataOnly){
1218  // all values required to update state vector lie in this rank
1219  statevec_hadamardLocal(qureg, targetQubit);
1220  } else {
1221  // need to get corresponding chunk of state vector from other rank
1222  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1223  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1224  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
1225  // get corresponding values from my pair
1226  exchangeStateVectors(qureg, pairRank);
1227  // this rank's values are either in the upper of lower half of the block. send values to hadamardDistributed
1228  // in the correct order
1229  if (rankIsUpper){
1231  qureg.stateVec, //upper
1232  qureg.pairStateVec, //lower
1233  qureg.stateVec, rankIsUpper); //output
1234  } else {
1236  qureg.pairStateVec, //upper
1237  qureg.stateVec, //lower
1238  qureg.stateVec, rankIsUpper); //output
1239  }
1240  }
1241 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_hadamardDistributed(), and statevec_hadamardLocal().

Referenced by hadamard().

◆ statevec_initBlankState()

void statevec_initBlankState ( Qureg  qureg)

Definition at line 1366 of file QuEST_cpu.c.

1367 {
1368  long long int stateVecSize;
1369  long long int index;
1370 
1371  // dimension of the state vector
1372  stateVecSize = qureg.numAmpsPerChunk;
1373 
1374  // Can't use qureg->stateVec as a private OMP var
1375  qreal *stateVecReal = qureg.stateVec.real;
1376  qreal *stateVecImag = qureg.stateVec.imag;
1377 
1378  // initialise the state-vector to all-zeroes
1379 # ifdef _OPENMP
1380 # pragma omp parallel \
1381  default (none) \
1382  shared (stateVecSize, stateVecReal, stateVecImag) \
1383  private (index)
1384 # endif
1385  {
1386 # ifdef _OPENMP
1387 # pragma omp for schedule (static)
1388 # endif
1389  for (index=0; index<stateVecSize; index++) {
1390  stateVecReal[index] = 0.0;
1391  stateVecImag[index] = 0.0;
1392  }
1393  }
1394 }

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

Referenced by initBlankState(), statevec_applyPauliSum(), and statevec_initZeroState().

◆ statevec_initClassicalState()

void statevec_initClassicalState ( Qureg  qureg,
long long int  stateInd 
)

Definition at line 1438 of file QuEST_cpu.c.

1439 {
1440  long long int stateVecSize;
1441  long long int index;
1442 
1443  // dimension of the state vector
1444  stateVecSize = qureg.numAmpsPerChunk;
1445 
1446  // Can't use qureg->stateVec as a private OMP var
1447  qreal *stateVecReal = qureg.stateVec.real;
1448  qreal *stateVecImag = qureg.stateVec.imag;
1449 
1450  // initialise the state to vector to all zeros
1451 # ifdef _OPENMP
1452 # pragma omp parallel \
1453  default (none) \
1454  shared (stateVecSize, stateVecReal, stateVecImag) \
1455  private (index)
1456 # endif
1457  {
1458 # ifdef _OPENMP
1459 # pragma omp for schedule (static)
1460 # endif
1461  for (index=0; index<stateVecSize; index++) {
1462  stateVecReal[index] = 0.0;
1463  stateVecImag[index] = 0.0;
1464  }
1465  }
1466 
1467  // give the specified classical state prob 1
1468  if (qureg.chunkId == stateInd/stateVecSize){
1469  stateVecReal[stateInd % stateVecSize] = 1.0;
1470  stateVecImag[stateInd % stateVecSize] = 0.0;
1471  }
1472 }

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

Referenced by initClassicalState().

◆ statevec_initDebugState()

void statevec_initDebugState ( Qureg  qureg)

Initialise the state vector of probability amplitudes to an (unphysical) state with each component of each probability amplitude a unique floating point value.

For debugging processes

Parameters
[in,out]quregobject representing the set of qubits to be initialised

Definition at line 1559 of file QuEST_cpu.c.

1560 {
1561  long long int chunkSize;
1562  long long int index;
1563  long long int indexOffset;
1564 
1565  // dimension of the state vector
1566  chunkSize = qureg.numAmpsPerChunk;
1567 
1568  // Can't use qureg->stateVec as a private OMP var
1569  qreal *stateVecReal = qureg.stateVec.real;
1570  qreal *stateVecImag = qureg.stateVec.imag;
1571 
1572  indexOffset = chunkSize * qureg.chunkId;
1573 
1574  // initialise the state to |0000..0000>
1575 # ifdef _OPENMP
1576 # pragma omp parallel \
1577  default (none) \
1578  shared (chunkSize, stateVecReal, stateVecImag, indexOffset) \
1579  private (index)
1580 # endif
1581  {
1582 # ifdef _OPENMP
1583 # pragma omp for schedule (static)
1584 # endif
1585  for (index=0; index<chunkSize; index++) {
1586  stateVecReal[index] = ((indexOffset + index)*2.0)/10.0;
1587  stateVecImag[index] = ((indexOffset + index)*2.0+1.0)/10.0;
1588  }
1589  }
1590 }

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

Referenced by initDebugState().

◆ statevec_initPlusState()

void statevec_initPlusState ( Qureg  qureg)

Definition at line 1406 of file QuEST_cpu.c.

1407 {
1408  long long int chunkSize, stateVecSize;
1409  long long int index;
1410 
1411  // dimension of the state vector
1412  chunkSize = qureg.numAmpsPerChunk;
1413  stateVecSize = chunkSize*qureg.numChunks;
1414  qreal normFactor = 1.0/sqrt((qreal)stateVecSize);
1415 
1416  // Can't use qureg->stateVec as a private OMP var
1417  qreal *stateVecReal = qureg.stateVec.real;
1418  qreal *stateVecImag = qureg.stateVec.imag;
1419 
1420  // initialise the state to |+++..+++> = 1/normFactor {1, 1, 1, ...}
1421 # ifdef _OPENMP
1422 # pragma omp parallel \
1423  default (none) \
1424  shared (chunkSize, stateVecReal, stateVecImag, normFactor) \
1425  private (index)
1426 # endif
1427  {
1428 # ifdef _OPENMP
1429 # pragma omp for schedule (static)
1430 # endif
1431  for (index=0; index<chunkSize; index++) {
1432  stateVecReal[index] = normFactor;
1433  stateVecImag[index] = 0.0;
1434  }
1435  }
1436 }

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

Referenced by initPlusState().

◆ statevec_initStateFromSingleFile()

int statevec_initStateFromSingleFile ( Qureg qureg,
char  filename[200],
QuESTEnv  env 
)

Definition at line 1593 of file QuEST_cpu.c.

1593  {
1594  long long int chunkSize, stateVecSize;
1595  long long int indexInChunk, totalIndex;
1596 
1597  chunkSize = qureg->numAmpsPerChunk;
1598  stateVecSize = chunkSize*qureg->numChunks;
1599 
1600  qreal *stateVecReal = qureg->stateVec.real;
1601  qreal *stateVecImag = qureg->stateVec.imag;
1602 
1603  FILE *fp;
1604  char line[200];
1605 
1606  for (int rank=0; rank<(qureg->numChunks); rank++){
1607  if (rank==qureg->chunkId){
1608  fp = fopen(filename, "r");
1609 
1610  // indicate file open failure
1611  if (fp == NULL)
1612  return 0;
1613 
1614  indexInChunk = 0; totalIndex = 0;
1615  while (fgets(line, sizeof(char)*200, fp) != NULL && totalIndex<stateVecSize){
1616  if (line[0]!='#'){
1617  int chunkId = (int) (totalIndex/chunkSize);
1618  if (chunkId==qureg->chunkId){
1619  # if QuEST_PREC==1
1620  sscanf(line, "%f, %f", &(stateVecReal[indexInChunk]),
1621  &(stateVecImag[indexInChunk]));
1622  # elif QuEST_PREC==2
1623  sscanf(line, "%lf, %lf", &(stateVecReal[indexInChunk]),
1624  &(stateVecImag[indexInChunk]));
1625  # elif QuEST_PREC==4
1626  sscanf(line, "%Lf, %Lf", &(stateVecReal[indexInChunk]),
1627  &(stateVecImag[indexInChunk]));
1628  # endif
1629  indexInChunk += 1;
1630  }
1631  totalIndex += 1;
1632  }
1633  }
1634  fclose(fp);
1635  }
1636  syncQuESTEnv(env);
1637  }
1638 
1639  // indicate success
1640  return 1;
1641 }

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

Referenced by initStateFromSingleFile().

◆ statevec_initStateOfSingleQubit()

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 other qubits are in an equal superposition of zero and one.

Parameters
[in,out]quregobject representing the set of qubits to be initialised
[in]qubitIdid of qubit to set to state 'outcome'
[in]valueof qubit 'qubitId'

Definition at line 1513 of file QuEST_cpu.c.

1514 {
1515  long long int chunkSize, stateVecSize;
1516  long long int index;
1517  int bit;
1518  const long long int chunkId=qureg->chunkId;
1519 
1520  // dimension of the state vector
1521  chunkSize = qureg->numAmpsPerChunk;
1522  stateVecSize = chunkSize*qureg->numChunks;
1523  qreal normFactor = 1.0/sqrt((qreal)stateVecSize/2.0);
1524 
1525  // Can't use qureg->stateVec as a private OMP var
1526  qreal *stateVecReal = qureg->stateVec.real;
1527  qreal *stateVecImag = qureg->stateVec.imag;
1528 
1529  // initialise the state to |0000..0000>
1530 # ifdef _OPENMP
1531 # pragma omp parallel \
1532  default (none) \
1533  shared (chunkSize, stateVecReal, stateVecImag, normFactor, qubitId, outcome) \
1534  private (index, bit)
1535 # endif
1536  {
1537 # ifdef _OPENMP
1538 # pragma omp for schedule (static)
1539 # endif
1540  for (index=0; index<chunkSize; index++) {
1541  bit = extractBit(qubitId, index+chunkId*chunkSize);
1542  if (bit==outcome) {
1543  stateVecReal[index] = normFactor;
1544  stateVecImag[index] = 0.0;
1545  } else {
1546  stateVecReal[index] = 0.0;
1547  stateVecImag[index] = 0.0;
1548  }
1549  }
1550  }
1551 }

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

Referenced by initStateOfSingleQubit().

◆ statevec_initZeroState()

void statevec_initZeroState ( Qureg  qureg)

Definition at line 1396 of file QuEST_cpu.c.

1397 {
1398  statevec_initBlankState(qureg);
1399  if (qureg.chunkId==0){
1400  // zero state |0000..0000> has probability 1
1401  qureg.stateVec.real[0] = 1.0;
1402  qureg.stateVec.imag[0] = 0.0;
1403  }
1404 }

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

Referenced by initZeroState().

◆ statevec_measureWithStats()

int statevec_measureWithStats ( Qureg  qureg,
int  measureQubit,
qreal outcomeProb 
)

Definition at line 360 of file QuEST_common.c.

360  {
361 
362  qreal zeroProb = statevec_calcProbOfOutcome(qureg, measureQubit, 0);
363  int outcome = generateMeasurementOutcome(zeroProb, outcomeProb);
364  statevec_collapseToKnownProbOutcome(qureg, measureQubit, outcome, *outcomeProb);
365  return outcome;
366 }

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

Referenced by measure(), and measureWithStats().

◆ statevec_multiControlledMultiQubitUnitary()

void statevec_multiControlledMultiQubitUnitary ( Qureg  qureg,
long long int  ctrlMask,
int *  targs,
const int  numTargs,
ComplexMatrixN  u 
)

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

It is already gauranteed here that all target qubits can fit on each node (this is validated in the front-end)

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated.

Definition at line 1441 of file QuEST_cpu_distributed.c.

1441  {
1442 
1443  // bit mask of target qubits (for quick collision checking)
1444  long long int targMask = getQubitBitMask(targs, numTargs);
1445 
1446  // find lowest qubit available for swapping (isn't in targs)
1447  int freeQb=0;
1448  while (maskContainsBit(targMask, freeQb))
1449  freeQb++;
1450 
1451  // assign indices of where each target will be swapped to (else itself)
1452  int swapTargs[numTargs];
1453  for (int t=0; t<numTargs; t++) {
1454  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targs[t]))
1455  swapTargs[t] = targs[t];
1456  else {
1457  // mark swap
1458  swapTargs[t] = freeQb;
1459 
1460  // update ctrlMask if swapped-out qubit was a control
1461  if (maskContainsBit(ctrlMask, swapTargs[t]))
1462  ctrlMask = flipBit(flipBit(ctrlMask, swapTargs[t]), targs[t]); // swap targ and ctrl
1463 
1464  // locate next available on-chunk qubit
1465  freeQb++;
1466  while (maskContainsBit(targMask, freeQb))
1467  freeQb++;
1468  }
1469  }
1470 
1471  // perform swaps as necessary
1472  for (int t=0; t<numTargs; t++)
1473  if (swapTargs[t] != targs[t])
1474  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
1475 
1476  // all target qubits have now been swapped into local memory
1477  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, swapTargs, numTargs, u);
1478 
1479  // undo swaps
1480  for (int t=0; t<numTargs; t++)
1481  if (swapTargs[t] != targs[t])
1482  statevec_swapQubitAmps(qureg, targs[t], swapTargs[t]);
1483 }

References flipBit(), getQubitBitMask(), halfMatrixBlockFitsInChunk(), ComplexMatrixN::imag, maskContainsBit(), Qureg::numAmpsPerChunk, ComplexMatrixN::numQubits, qreal, ComplexMatrixN::real, statevec_multiControlledMultiQubitUnitaryLocal(), and statevec_swapQubitAmps().

Referenced by densmatr_applyMultiQubitKrausSuperoperator(), densmatr_applyTwoQubitKrausSuperoperator(), multiControlledMultiQubitUnitary(), statevec_controlledMultiQubitUnitary(), and statevec_multiQubitUnitary().

◆ statevec_multiControlledPhaseFlip()

void statevec_multiControlledPhaseFlip ( Qureg  qureg,
int *  controlQubits,
int  numControlQubits 
)

Definition at line 3291 of file QuEST_cpu.c.

3292 {
3293  long long int index;
3294  long long int stateVecSize;
3295 
3296  const long long int chunkSize=qureg.numAmpsPerChunk;
3297  const long long int chunkId=qureg.chunkId;
3298 
3299  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
3300 
3301  stateVecSize = qureg.numAmpsPerChunk;
3302  qreal *stateVecReal = qureg.stateVec.real;
3303  qreal *stateVecImag = qureg.stateVec.imag;
3304 
3305 # ifdef _OPENMP
3306 # pragma omp parallel \
3307  default (none) \
3308  shared (stateVecSize, stateVecReal,stateVecImag, mask ) \
3309  private (index)
3310 # endif
3311  {
3312 # ifdef _OPENMP
3313 # pragma omp for schedule (static)
3314 # endif
3315  for (index=0; index<stateVecSize; index++) {
3316  if (mask == (mask & (index+chunkId*chunkSize)) ){
3317  stateVecReal [index] = - stateVecReal [index];
3318  stateVecImag [index] = - stateVecImag [index];
3319  }
3320  }
3321  }
3322 }

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

Referenced by multiControlledPhaseFlip().

◆ statevec_multiControlledPhaseShift()

void statevec_multiControlledPhaseShift ( Qureg  qureg,
int *  controlQubits,
int  numControlQubits,
qreal  angle 
)

Definition at line 3019 of file QuEST_cpu.c.

3020 {
3021  long long int index;
3022  long long int stateVecSize;
3023 
3024  const long long int chunkSize=qureg.numAmpsPerChunk;
3025  const long long int chunkId=qureg.chunkId;
3026 
3027  long long int mask = getQubitBitMask(controlQubits, numControlQubits);
3028 
3029  stateVecSize = qureg.numAmpsPerChunk;
3030  qreal *stateVecReal = qureg.stateVec.real;
3031  qreal *stateVecImag = qureg.stateVec.imag;
3032 
3033  qreal stateRealLo, stateImagLo;
3034  const qreal cosAngle = cos(angle);
3035  const qreal sinAngle = sin(angle);
3036 
3037 # ifdef _OPENMP
3038 # pragma omp parallel \
3039  default (none) \
3040  shared (stateVecSize, stateVecReal, stateVecImag, mask) \
3041  private (index, stateRealLo, stateImagLo)
3042 # endif
3043  {
3044 # ifdef _OPENMP
3045 # pragma omp for schedule (static)
3046 # endif
3047  for (index=0; index<stateVecSize; index++) {
3048  if (mask == (mask & (index+chunkId*chunkSize)) ){
3049 
3050  stateRealLo = stateVecReal[index];
3051  stateImagLo = stateVecImag[index];
3052 
3053  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
3054  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
3055  }
3056  }
3057  }
3058 }

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

Referenced by multiControlledPhaseShift().

◆ statevec_multiControlledTwoQubitUnitary()

void statevec_multiControlledTwoQubitUnitary ( Qureg  qureg,
long long int  ctrlMask,
const int  q1,
const int  q2,
ComplexMatrix4  u 
)

This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks already fit in the node, it operates the unitary direct.

Note the order of q1 and q2 in the call to twoQubitUnitaryLocal is important.

@TODO: refactor so that the 'swap back' isn't performed; instead the qubit locations are updated. @TODO: the double swap (q1,q2 to 0,1) may be possible simultaneously by a bespoke swap routine.

Definition at line 1385 of file QuEST_cpu_distributed.c.

1385  {
1386  int q1FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q1);
1387  int q2FitsInNode = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, q2);
1388 
1389  if (q1FitsInNode && q2FitsInNode) {
1390  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
1391 
1392  } else if (q1FitsInNode) {
1393  int qSwap = (q1 > 0)? q1-1 : q1+1;
1394 
1395  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
1396  if (maskContainsBit(ctrlMask, qSwap))
1397  ctrlMask = flipBit(flipBit(ctrlMask, q2), qSwap);
1398 
1399  statevec_swapQubitAmps(qureg, q2, qSwap);
1400  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, qSwap, u);
1401  statevec_swapQubitAmps(qureg, q2, qSwap);
1402 
1403  } else if (q2FitsInNode) {
1404  int qSwap = (q2 > 0)? q2-1 : q2+1;
1405 
1406  // ensure ctrl == qSwap, ensure ctrlMask updates under the swap
1407  if (maskContainsBit(ctrlMask, qSwap))
1408  ctrlMask = flipBit(flipBit(ctrlMask, q1), qSwap);
1409 
1410  statevec_swapQubitAmps(qureg, q1, qSwap);
1411  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, qSwap, q2, u);
1412  statevec_swapQubitAmps(qureg, q1, qSwap);
1413 
1414  } else {
1415  // we know with certainty that both q1 and q2 >= 2
1416  int swap1 = 0;
1417  int swap2 = 1;
1418 
1419  // if ctrl == swap1 or swap2, ensure ctrlMask updates under the swap
1420  if (maskContainsBit(ctrlMask, swap1))
1421  ctrlMask = flipBit(flipBit(ctrlMask, swap1), q1);
1422  if (maskContainsBit(ctrlMask, swap2))
1423  ctrlMask = flipBit(flipBit(ctrlMask, swap2), q2);
1424 
1425  statevec_swapQubitAmps(qureg, q1, swap1);
1426  statevec_swapQubitAmps(qureg, q2, swap2);
1427  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, swap1, swap2, u);
1428  statevec_swapQubitAmps(qureg, q1, swap1);
1429  statevec_swapQubitAmps(qureg, q2, swap2);
1430  }
1431 }

References flipBit(), halfMatrixBlockFitsInChunk(), maskContainsBit(), Qureg::numAmpsPerChunk, qreal, statevec_multiControlledTwoQubitUnitaryLocal(), and statevec_swapQubitAmps().

Referenced by densmatr_applyKrausSuperoperator(), multiControlledTwoQubitUnitary(), statevec_controlledTwoQubitUnitary(), and statevec_twoQubitUnitary().

◆ statevec_multiControlledUnitary()

void statevec_multiControlledUnitary ( Qureg  qureg,
long long int  ctrlQubitsMask,
long long int  ctrlFlipMask,
const int  targetQubit,
ComplexMatrix2  u 
)

Definition at line 999 of file QuEST_cpu_distributed.c.

1000 {
1001  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
1002  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1003  Complex rot1, rot2;
1004 
1005  // rank's chunk is in upper half of block
1006  int rankIsUpper;
1007  int pairRank; // rank of corresponding chunk
1008 
1009  if (useLocalDataOnly){
1010  // all values required to update state vector lie in this rank
1011  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
1012  } else {
1013  // need to get corresponding chunk of state vector from other rank
1014  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1015  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
1016  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1017 
1018  // get corresponding values from my pair
1019  exchangeStateVectors(qureg, pairRank);
1020 
1021  // this rank's values are either in the upper of lower half of the block. send values to multiControlledUnitaryDistributed
1022  // in the correct order
1023  if (rankIsUpper){
1024  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
1025  qureg.stateVec, //upper
1026  qureg.pairStateVec, //lower
1027  qureg.stateVec); //output
1028  } else {
1029  statevec_multiControlledUnitaryDistributed(qureg,targetQubit,ctrlQubitsMask,ctrlFlipMask,rot1,rot2,
1030  qureg.pairStateVec, //upper
1031  qureg.stateVec, //lower
1032  qureg.stateVec); //output
1033  }
1034  }
1035 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_multiControlledUnitaryDistributed(), and statevec_multiControlledUnitaryLocal().

Referenced by multiControlledUnitary(), and multiStateControlledUnitary().

◆ statevec_multiQubitUnitary()

void statevec_multiQubitUnitary ( Qureg  qureg,
int *  targets,
const int  numTargets,
ComplexMatrixN  u 
)

Definition at line 528 of file QuEST_common.c.

528  {
529 
530  long long int ctrlMask = 0;
531  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targets, numTargets, u);
532 }

References statevec_multiControlledMultiQubitUnitary().

Referenced by multiQubitUnitary().

◆ statevec_multiRotatePauli()

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 at line 410 of file QuEST_common.c.

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

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

Referenced by multiRotatePauli().

◆ statevec_multiRotateZ()

void statevec_multiRotateZ ( Qureg  qureg,
long long int  mask,
qreal  angle 
)

Definition at line 3069 of file QuEST_cpu.c.

3070 {
3071  long long int index;
3072  long long int stateVecSize;
3073 
3074  const long long int chunkSize=qureg.numAmpsPerChunk;
3075  const long long int chunkId=qureg.chunkId;
3076 
3077  stateVecSize = qureg.numAmpsPerChunk;
3078  qreal *stateVecReal = qureg.stateVec.real;
3079  qreal *stateVecImag = qureg.stateVec.imag;
3080 
3081  qreal stateReal, stateImag;
3082  const qreal cosAngle = cos(angle/2.0);
3083  const qreal sinAngle = sin(angle/2.0);
3084 
3085  // = +-1, to flip sinAngle based on target qubit parity, to effect
3086  // exp(-angle/2 i fac_j)|j>
3087  int fac;
3088 
3089 # ifdef _OPENMP
3090 # pragma omp parallel \
3091  default (none) \
3092  shared (stateVecSize, stateVecReal, stateVecImag, mask) \
3093  private (index, fac, stateReal, stateImag)
3094 # endif
3095  {
3096 # ifdef _OPENMP
3097 # pragma omp for schedule (static)
3098 # endif
3099  for (index=0; index<stateVecSize; index++) {
3100  stateReal = stateVecReal[index];
3101  stateImag = stateVecImag[index];
3102 
3103  // odd-parity target qubits get fac_j = -1
3104  fac = getBitMaskParity(mask & (index+chunkId*chunkSize))? -1 : 1;
3105  stateVecReal[index] = cosAngle*stateReal + fac * sinAngle*stateImag;
3106  stateVecImag[index] = - fac * sinAngle*stateReal + cosAngle*stateImag;
3107  }
3108  }
3109 }

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

Referenced by multiRotateZ(), and statevec_multiRotatePauli().

◆ statevec_pauliX()

void statevec_pauliX ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 1036 of file QuEST_cpu_distributed.c.

1037 {
1038  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
1039  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1040 
1041  // rank's chunk is in upper half of block
1042  int rankIsUpper;
1043  int pairRank; // rank of corresponding chunk
1044 
1045  if (useLocalDataOnly){
1046  // all values required to update state vector lie in this rank
1047  statevec_pauliXLocal(qureg, targetQubit);
1048  } else {
1049  // need to get corresponding chunk of state vector from other rank
1050  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1051  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1052  //printf("%d rank has pair rank: %d\n", qureg.rank, pairRank);
1053  // get corresponding values from my pair
1054  exchangeStateVectors(qureg, pairRank);
1055  // this rank's values are either in the upper of lower half of the block. pauliX just replaces
1056  // this rank's values with pair values
1058  qureg.pairStateVec, // in
1059  qureg.stateVec); // out
1060  }
1061 }

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().

◆ statevec_pauliY()

void statevec_pauliY ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 1092 of file QuEST_cpu_distributed.c.

1093 {
1094  int conjFac = 1;
1095 
1096  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
1097  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1098  int rankIsUpper; // rank's chunk is in upper half of block
1099  int pairRank; // rank of corresponding chunk
1100 
1101  if (useLocalDataOnly){
1102  statevec_pauliYLocal(qureg, targetQubit, conjFac);
1103  } else {
1104  // need to get corresponding chunk of state vector from other rank
1105  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1106  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1107  // get corresponding values from my pair
1108  exchangeStateVectors(qureg, pairRank);
1109  // this rank's values are either in the upper of lower half of the block
1111  qureg.pairStateVec, // in
1112  qureg.stateVec, // out
1113  rankIsUpper, conjFac);
1114  }
1115 }

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().

◆ statevec_pauliYConj()

void statevec_pauliYConj ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 1117 of file QuEST_cpu_distributed.c.

1118 {
1119  int conjFac = -1;
1120 
1121  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
1122  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
1123  int rankIsUpper; // rank's chunk is in upper half of block
1124  int pairRank; // rank of corresponding chunk
1125 
1126  if (useLocalDataOnly){
1127  statevec_pauliYLocal(qureg, targetQubit, conjFac);
1128  } else {
1129  // need to get corresponding chunk of state vector from other rank
1130  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1131  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
1132  // get corresponding values from my pair
1133  exchangeStateVectors(qureg, pairRank);
1134  // this rank's values are either in the upper of lower half of the block
1136  qureg.pairStateVec, // in
1137  qureg.stateVec, // out
1138  rankIsUpper, conjFac);
1139  }
1140 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_pauliYDistributed(), and statevec_pauliYLocal().

Referenced by pauliY().

◆ statevec_pauliZ()

void statevec_pauliZ ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 257 of file QuEST_common.c.

257  {
258  Complex term;
259  term.real = -1;
260  term.imag = 0;
261  statevec_phaseShiftByTerm(qureg, targetQubit, term);
262 }

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

Referenced by pauliZ(), and statevec_applyPauliProd().

◆ statevec_phaseShift()

void statevec_phaseShift ( Qureg  qureg,
const int  targetQubit,
qreal  angle 
)

Definition at line 250 of file QuEST_common.c.

250  {
251  Complex term;
252  term.real = cos(angle);
253  term.imag = sin(angle);
254  statevec_phaseShiftByTerm(qureg, targetQubit, term);
255 }

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

Referenced by phaseShift().

◆ statevec_phaseShiftByTerm()

void statevec_phaseShiftByTerm ( Qureg  qureg,
const int  targetQubit,
Complex  term 
)

Definition at line 2940 of file QuEST_cpu.c.

2941 {
2942  long long int index;
2943  long long int stateVecSize;
2944  int targetBit;
2945 
2946  const long long int chunkSize=qureg.numAmpsPerChunk;
2947  const long long int chunkId=qureg.chunkId;
2948 
2949  // dimension of the state vector
2950  stateVecSize = qureg.numAmpsPerChunk;
2951  qreal *stateVecReal = qureg.stateVec.real;
2952  qreal *stateVecImag = qureg.stateVec.imag;
2953 
2954  qreal stateRealLo, stateImagLo;
2955  const qreal cosAngle = term.real;
2956  const qreal sinAngle = term.imag;
2957 
2958 # ifdef _OPENMP
2959 # pragma omp parallel for \
2960  default (none) \
2961  shared (stateVecSize, stateVecReal,stateVecImag ) \
2962  private (index,targetBit,stateRealLo,stateImagLo) \
2963  schedule (static)
2964 # endif
2965  for (index=0; index<stateVecSize; index++) {
2966 
2967  // update the coeff of the |1> state of the target qubit
2968  targetBit = extractBit (targetQubit, index+chunkId*chunkSize);
2969  if (targetBit) {
2970 
2971  stateRealLo = stateVecReal[index];
2972  stateImagLo = stateVecImag[index];
2973 
2974  stateVecReal[index] = cosAngle*stateRealLo - sinAngle*stateImagLo;
2975  stateVecImag[index] = sinAngle*stateRealLo + cosAngle*stateImagLo;
2976  }
2977  }
2978 }

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().

◆ statevec_reportStateToScreen()

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.

For debugging purposes. Each rank should print output serially. Only print output for systems <= 5 qubits

Definition at line 1334 of file QuEST_cpu.c.

1334  {
1335  long long int index;
1336  int rank;
1337  if (qureg.numQubitsInStateVec<=5){
1338  for (rank=0; rank<qureg.numChunks; rank++){
1339  if (qureg.chunkId==rank){
1340  if (reportRank) {
1341  printf("Reporting state from rank %d [\n", qureg.chunkId);
1342  printf("real, imag\n");
1343  } else if (rank==0) {
1344  printf("Reporting state [\n");
1345  printf("real, imag\n");
1346  }
1347 
1348  for(index=0; index<qureg.numAmpsPerChunk; index++){
1349  //printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.pairStateVec.real[index], qureg.pairStateVec.imag[index]);
1350  printf(REAL_STRING_FORMAT ", " REAL_STRING_FORMAT "\n", qureg.stateVec.real[index], qureg.stateVec.imag[index]);
1351  }
1352  if (reportRank || rank==qureg.numChunks-1) printf("]\n");
1353  }
1354  syncQuESTEnv(env);
1355  }
1356  } else printf("Error: reportStateToScreen will not print output for systems of more than 5 qubits.\n");
1357 }

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

Referenced by reportStateToScreen().

◆ statevec_rotateAroundAxis()

void statevec_rotateAroundAxis ( Qureg  qureg,
const int  rotQubit,
qreal  angle,
Vector  axis 
)

Definition at line 310 of file QuEST_common.c.

310  {
311 
312  Complex alpha, beta;
313  getComplexPairFromRotation(angle, axis, &alpha, &beta);
314  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
315 }

References getComplexPairFromRotation(), and statevec_compactUnitary().

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

◆ statevec_rotateAroundAxisConj()

void statevec_rotateAroundAxisConj ( Qureg  qureg,
const int  rotQubit,
qreal  angle,
Vector  axis 
)

Definition at line 317 of file QuEST_common.c.

317  {
318 
319  Complex alpha, beta;
320  getComplexPairFromRotation(angle, axis, &alpha, &beta);
321  alpha.imag *= -1;
322  beta.imag *= -1;
323  statevec_compactUnitary(qureg, rotQubit, alpha, beta);
324 }

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

Referenced by rotateAroundAxis().

◆ statevec_rotateX()

void statevec_rotateX ( Qureg  qureg,
const int  rotQubit,
qreal  angle 
)

Definition at line 292 of file QuEST_common.c.

292  {
293 
294  Vector unitAxis = {1, 0, 0};
295  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
296 }

References statevec_rotateAroundAxis().

Referenced by rotateX().

◆ statevec_rotateY()

void statevec_rotateY ( Qureg  qureg,
const int  rotQubit,
qreal  angle 
)

Definition at line 298 of file QuEST_common.c.

298  {
299 
300  Vector unitAxis = {0, 1, 0};
301  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
302 }

References statevec_rotateAroundAxis().

Referenced by rotateY().

◆ statevec_rotateZ()

void statevec_rotateZ ( Qureg  qureg,
const int  rotQubit,
qreal  angle 
)

Definition at line 304 of file QuEST_common.c.

304  {
305 
306  Vector unitAxis = {0, 0, 1};
307  statevec_rotateAroundAxis(qureg, rotQubit, angle, unitAxis);
308 }

References statevec_rotateAroundAxis().

Referenced by rotateZ().

◆ statevec_setAmps()

void statevec_setAmps ( Qureg  qureg,
long long int  startInd,
qreal reals,
qreal imags,
long long int  numAmps 
)

Definition at line 1236 of file QuEST_cpu.c.

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

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

Referenced by initStateFromAmps(), setAmps(), and setDensityAmps().

◆ statevec_setWeightedQureg()

void statevec_setWeightedQureg ( Complex  fac1,
Qureg  qureg1,
Complex  fac2,
Qureg  qureg2,
Complex  facOut,
Qureg  out 
)

Definition at line 3579 of file QuEST_cpu.c.

3579  {
3580 
3581  long long int numAmps = qureg1.numAmpsPerChunk;
3582 
3583  qreal *vecRe1 = qureg1.stateVec.real;
3584  qreal *vecIm1 = qureg1.stateVec.imag;
3585  qreal *vecRe2 = qureg2.stateVec.real;
3586  qreal *vecIm2 = qureg2.stateVec.imag;
3587  qreal *vecReOut = out.stateVec.real;
3588  qreal *vecImOut = out.stateVec.imag;
3589 
3590  qreal facRe1 = fac1.real;
3591  qreal facIm1 = fac1.imag;
3592  qreal facRe2 = fac2.real;
3593  qreal facIm2 = fac2.imag;
3594  qreal facReOut = facOut.real;
3595  qreal facImOut = facOut.imag;
3596 
3597  qreal re1,im1, re2,im2, reOut,imOut;
3598  long long int index;
3599 
3600 # ifdef _OPENMP
3601 # pragma omp parallel \
3602  shared (vecRe1,vecIm1, vecRe2,vecIm2, vecReOut,vecImOut, facRe1,facIm1,facRe2,facIm2, numAmps) \
3603  private (index, re1,im1, re2,im2, reOut,imOut)
3604 # endif
3605  {
3606 # ifdef _OPENMP
3607 # pragma omp for schedule (static)
3608 # endif
3609  for (index=0LL; index<numAmps; index++) {
3610  re1 = vecRe1[index]; im1 = vecIm1[index];
3611  re2 = vecRe2[index]; im2 = vecIm2[index];
3612  reOut = vecReOut[index];
3613  imOut = vecImOut[index];
3614 
3615  vecReOut[index] = (facReOut*reOut - facImOut*imOut) + (facRe1*re1 - facIm1*im1) + (facRe2*re2 - facIm2*im2);
3616  vecImOut[index] = (facReOut*imOut + facImOut*reOut) + (facRe1*im1 + facIm1*re1) + (facRe2*im2 + facIm2*re2);
3617  }
3618  }
3619 }

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

Referenced by setWeightedQureg(), and statevec_applyPauliSum().

◆ statevec_sGate()

void statevec_sGate ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 264 of file QuEST_common.c.

264  {
265  Complex term;
266  term.real = 0;
267  term.imag = 1;
268  statevec_phaseShiftByTerm(qureg, targetQubit, term);
269 }

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

Referenced by sGate().

◆ statevec_sGateConj()

void statevec_sGateConj ( Qureg  qureg,
const int  targetQubit 
)

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 }

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

Referenced by sGate().

◆ statevec_sqrtSwapGate()

void statevec_sqrtSwapGate ( Qureg  qureg,
int  qb1,
int  qb2 
)

Definition at line 383 of file QuEST_common.c.

383  {
384 
385  ComplexMatrix4 u = (ComplexMatrix4) {.real={{0}}, .imag={{0}}};
386  u.real[0][0]=1;
387  u.real[3][3]=1;
388  u.real[1][1] = .5; u.imag[1][1] = .5;
389  u.real[1][2] = .5; u.imag[1][2] =-.5;
390  u.real[2][1] = .5; u.imag[2][1] =-.5;
391  u.real[2][2] = .5; u.imag[2][2] = .5;
392 
393  statevec_twoQubitUnitary(qureg, qb1, qb2, u);
394 }

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

Referenced by sqrtSwapGate().

◆ statevec_sqrtSwapGateConj()

void statevec_sqrtSwapGateConj ( Qureg  qureg,
int  qb1,
int  qb2 
)

Definition at line 396 of file QuEST_common.c.

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

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

Referenced by sqrtSwapGate().

◆ statevec_swapQubitAmps()

void statevec_swapQubitAmps ( Qureg  qureg,
int  qb1,
int  qb2 
)

Definition at line 1358 of file QuEST_cpu_distributed.c.

1358  {
1359 
1360  // perform locally if possible
1361  int qbBig = (qb1 > qb2)? qb1 : qb2;
1362  if (halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, qbBig))
1363  return statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
1364 
1365  // do nothing if this node contains no amplitudes to swap
1366  long long int oddParityGlobalInd = getGlobalIndOfOddParityInChunk(qureg, qb1, qb2);
1367  if (oddParityGlobalInd == -1)
1368  return;
1369 
1370  // determine and swap amps with pair node
1371  int pairRank = flipBit(flipBit(oddParityGlobalInd, qb1), qb2) / qureg.numAmpsPerChunk;
1372  exchangeStateVectors(qureg, pairRank);
1373  statevec_swapQubitAmpsDistributed(qureg, pairRank, qb1, qb2);
1374 }

References exchangeStateVectors(), flipBit(), getGlobalIndOfOddParityInChunk(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, qreal, statevec_swapQubitAmpsDistributed(), and statevec_swapQubitAmpsLocal().

Referenced by statevec_multiControlledMultiQubitUnitary(), statevec_multiControlledTwoQubitUnitary(), and swapGate().

◆ statevec_tGate()

void statevec_tGate ( Qureg  qureg,
const int  targetQubit 
)

Definition at line 271 of file QuEST_common.c.

271  {
272  Complex term;
273  term.real = 1/sqrt(2);
274  term.imag = 1/sqrt(2);
275  statevec_phaseShiftByTerm(qureg, targetQubit, term);
276 }

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

Referenced by tGate().

◆ statevec_tGateConj()

void statevec_tGateConj ( Qureg  qureg,
const int  targetQubit 
)

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 }

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

Referenced by tGate().

◆ statevec_twoQubitUnitary()

void statevec_twoQubitUnitary ( Qureg  qureg,
const int  targetQubit1,
const int  targetQubit2,
ComplexMatrix4  u 
)

Definition at line 516 of file QuEST_common.c.

516  {
517 
518  long long int ctrlMask = 0;
519  statevec_multiControlledTwoQubitUnitary(qureg, ctrlMask, targetQubit1, targetQubit2, u);
520 }

References statevec_multiControlledTwoQubitUnitary().

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

◆ statevec_unitary()

void statevec_unitary ( Qureg  qureg,
const int  targetQubit,
ComplexMatrix2  u 
)

Definition at line 883 of file QuEST_cpu_distributed.c.

884 {
885  // flag to require memory exchange. 1: an entire block fits on one rank, 0: at most half a block fits on one rank
886  int useLocalDataOnly = halfMatrixBlockFitsInChunk(qureg.numAmpsPerChunk, targetQubit);
887  Complex rot1, rot2;
888 
889  // rank's chunk is in upper half of block
890  int rankIsUpper;
891  int pairRank; // rank of corresponding chunk
892 
893  if (useLocalDataOnly){
894  // all values required to update state vector lie in this rank
895  statevec_unitaryLocal(qureg, targetQubit, u);
896  } else {
897  // need to get corresponding chunk of state vector from other rank
898  rankIsUpper = chunkIsUpper(qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
899  getRotAngleFromUnitaryMatrix(rankIsUpper, &rot1, &rot2, u);
900  pairRank = getChunkPairId(rankIsUpper, qureg.chunkId, qureg.numAmpsPerChunk, targetQubit);
901  // get corresponding values from my pair
902  exchangeStateVectors(qureg, pairRank);
903 
904  // this rank's values are either in the upper of lower half of the block.
905  // send values to compactUnitaryDistributed in the correct order
906  if (rankIsUpper){
907  statevec_unitaryDistributed(qureg,rot1,rot2,
908  qureg.stateVec, //upper
909  qureg.pairStateVec, //lower
910  qureg.stateVec); //output
911  } else {
912  statevec_unitaryDistributed(qureg,rot1,rot2,
913  qureg.pairStateVec, //upper
914  qureg.stateVec, //lower
915  qureg.stateVec); //output
916  }
917  }
918 
919 
920 }

References Qureg::chunkId, chunkIsUpper(), exchangeStateVectors(), getChunkPairId(), getRotAngleFromUnitaryMatrix(), halfMatrixBlockFitsInChunk(), Qureg::numAmpsPerChunk, Qureg::pairStateVec, qreal, Qureg::stateVec, statevec_unitaryDistributed(), and statevec_unitaryLocal().

Referenced by unitary().

Represents a 3-vector of real numbers.
Definition: QuEST.h:148
#define macro_setConjugateMatrix(dest, src, dim)
Definition: QuEST_common.c:92
qreal real[4][4]
Definition: QuEST.h:127
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:599
void compressPairVectorForSingleQubitDepolarise(Qureg qureg, const int targetQubit)
void statevec_hadamardLocal(Qureg qureg, const int targetQubit)
Definition: QuEST_cpu.c:2834
static void getRotAngle(int chunkIsUpper, Complex *rot1, Complex *rot2, Complex alpha, Complex beta)
Get rotation values for a given chunk.
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:922
void densmatr_mixTwoQubitDepolarisingDistributed(Qureg qureg, const int targetQubit, const int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:540
int rank
Definition: QuEST.h:201
void populateKrausSuperOperator4(ComplexMatrixN *superOp, ComplexMatrix4 *ops, int numOps)
Definition: QuEST_common.c:566
void statevec_controlledNotDistributed(Qureg qureg, const int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2612
void populateKrausSuperOperatorN(ComplexMatrixN *superOp, ComplexMatrixN *ops, int numOps)
Definition: QuEST_common.c:570
static int maskContainsBit(long long int mask, int bitInd)
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1021
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:464
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:181
@ 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:3222
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1000
qreal z
Definition: QuEST.h:150
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, const int q1, const int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1715
void densmatr_mixTwoQubitDepolarisingQ1LocalQ2DistributedPart3(Qureg qureg, const int targetQubit, const int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:631
int numChunks
Number of chunks the state vector is broken up into – the number of MPI processes used.
Definition: QuEST.h:176
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:3496
void statevec_applyPauliProd(Qureg workspace, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets)
Definition: QuEST_common.c:450
int getBitMaskParity(long long int mask)
Definition: QuEST_cpu.c:3060
void statevec_multiRotateZ(Qureg qureg, long long int mask, qreal angle)
Definition: QuEST_cpu.c:3069
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, const int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
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:3340
__forceinline__ __device__ int extractBit(int locationOfBitFromRight, long long int theEncodedNumber)
Definition: QuEST_gpu.cu:82
void densmatr_collapseToKnownProbOutcome(Qureg qureg, const int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:784
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, const int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3166
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:860
Vector getUnitVector(Vector vec)
Definition: QuEST_common.c:77
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1366
void getComplexPairFromRotation(qreal angle, Vector axis, Complex *alpha, Complex *beta)
Definition: QuEST_common.c:113
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
void statevec_pauliXDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut)
Rotate a single qubit by {{0,1},{1,0}.
Definition: QuEST_cpu.c:2522
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:628
void exchangePairStateVectorHalves(Qureg qureg, int pairRank)
@ PAULI_X
Definition: QuEST.h:96
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:167
void compressPairVectorForTwoQubitDepolarise(Qureg qureg, const int targetQubit, const int qubit2)
void statevec_controlledNotLocal(Qureg qureg, const int controlQubit, const int targetQubit)
Definition: QuEST_cpu.c:2550
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)
long long int getQubitBitMask(int *qubits, const int numQubits)
Definition: QuEST_common.c:43
void statevec_collapseToOutcomeDistributedSetZero(Qureg qureg)
Set all amplitudes in one chunk to 0.
Definition: QuEST_cpu.c:3461
int chunkId
The position of the chunk of the state vector held by this process in the full state vector.
Definition: QuEST.h:174
void densmatr_mixDampingLocal(Qureg qureg, const int targetQubit, qreal damping)
Definition: QuEST_cpu.c:174
qreal y
Definition: QuEST.h:150
qreal imag[2][2]
Definition: QuEST.h:117
void statevec_multiControlledUnitaryLocal(Qureg qureg, const int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2140
qreal x
Definition: QuEST.h:150
void statevec_controlledCompactUnitaryLocal(Qureg qureg, const int controlQubit, const int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2069
int generateMeasurementOutcome(qreal zeroProb, qreal *outcomeProb)
Definition: QuEST_common.c:154
void statevec_twoQubitUnitary(Qureg qureg, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:516
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:170
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:385
static void getRotAngleFromUnitaryMatrix(int chunkIsUpper, Complex *rot1, Complex *rot2, ComplexMatrix2 u)
Get rotation values for a given chunk given a unitary matrix.
void densmatr_mixDepolarisingDistributed(Qureg qureg, const int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:224
void densmatr_applyKrausSuperoperator(Qureg qureg, int target, ComplexMatrix4 superOp)
Definition: QuEST_common.c:575
void statevec_initBlankState(Qureg qureg)
Definition: QuEST_cpu.c:1366
void populateKrausSuperOperator2(ComplexMatrix4 *superOp, ComplexMatrix2 *ops, int numOps)
Definition: QuEST_common.c:562
void statevec_controlledUnitaryDistributed(Qureg qureg, const 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:2347
void alternateNormZeroingSomeAmpBlocks(Qureg qureg, qreal norm, int normFirst, long long int startAmpInd, long long int numAmps, long long int blockSize)
Definition: QuEST_cpu.c:753
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1474
int numRanks
Definition: QuEST.h:202
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:1969
qreal imag[4][4]
Definition: QuEST.h:128
void statevec_compactUnitaryLocal(Qureg qureg, const int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1656
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, const int measureQubit)
Definition: QuEST_cpu.c:3111
void statevec_phaseShiftByTerm(Qureg qureg, const int targetQubit, Complex term)
Definition: QuEST_cpu.c:2940
void exchangeStateVectors(Qureg qureg, int pairRank)
void normaliseSomeAmps(Qureg qureg, qreal norm, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:743
@ PAULI_Y
Definition: QuEST.h:96
void densmatr_mixTwoQubitDephasing(Qureg qureg, const int qubit1, const int qubit2, qreal dephase)
Definition: QuEST_cpu.c:84
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1183
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:3579
__forceinline__ __device__ long long int flipBit(long long int number, int bitInd)
Definition: QuEST_gpu.cu:95
void statevec_collapseToKnownProbOutcomeDistributedRenorm(Qureg qureg, const int measureQubit, const qreal totalProbability)
Renormalise parts of the state vector where measureQubit=0 or 1, based on the total probability of th...
Definition: QuEST_cpu.c:3422
qreal statevec_calcProbOfOutcome(Qureg qureg, const int measureQubit, int outcome)
void densmatr_mixDepolarisingLocal(Qureg qureg, const int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:125
void statevec_collapseToKnownProbOutcome(Qureg qureg, const int measureQubit, int outcome, qreal outcomeProb)
qreal statevec_getImagAmp(Qureg qureg, long long int index)
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:957
static int getChunkIdFromIndex(Qureg qureg, long long int index)
void statevec_pauliXLocal(Qureg qureg, const int targetQubit)
Definition: QuEST_cpu.c:2464
void statevec_controlledUnitaryLocal(Qureg qureg, const int controlQubit, const int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2207
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:2024
qreal densmatr_calcProbOfOutcome(Qureg qureg, const int measureQubit, int outcome)
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:179
void statevec_unitaryLocal(Qureg qureg, const int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:1900
qreal real[2][2]
Definition: QuEST.h:116
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_multiControlledUnitaryDistributed(Qureg qureg, const 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:2413
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:163
void statevec_controlledCompactUnitary(Qureg qureg, const int controlQubit, const int targetQubit, Complex alpha, Complex beta)
void statevec_controlledPauliYDistributed(Qureg qureg, const int controlQubit, ComplexArray stateVecIn, ComplexArray stateVecOut, const int conjFac)
Definition: QuEST_cpu.c:2793
int numQubits
Definition: QuEST.h:138
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_pauliYLocal(Qureg qureg, const int targetQubit, const int conjFac)
Definition: QuEST_cpu.c:2647
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, const int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1814
void densmatr_applyTwoQubitKrausSuperoperator(Qureg qureg, int target1, int target2, ComplexMatrixN superOp)
Definition: QuEST_common.c:581
void densmatr_mixTwoQubitDepolarisingLocalPart1(Qureg qureg, int qubit1, int qubit2, qreal delta)
Definition: QuEST_cpu.c:487
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:165
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:172
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:3539
void densmatr_applyMultiQubitKrausSuperoperator(Qureg qureg, int *targets, int numTargets, ComplexMatrixN superOp)
Definition: QuEST_common.c:589
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 statevec_pauliYDistributed(Qureg qureg, ComplexArray stateVecIn, ComplexArray stateVecOut, int updateUpper, const int conjFac)
Rotate a single qubit by +-{{0,-i},{i,0}.
Definition: QuEST_cpu.c:2704
static int chunkIsUpperInOuterBlock(int chunkId, long long int chunkSize, int targetQubit, int numQubits)
fix – do with masking instead
void statevec_controlledRotateAroundAxis(Qureg qureg, const int controlQubit, const int targetQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:326
void statevec_controlledCompactUnitaryDistributed(Qureg qureg, const 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:2285
Represents one complex number.
Definition: QuEST.h:103
void statevec_rotateAroundAxis(Qureg qureg, const int rotQubit, qreal angle, Vector axis)
Definition: QuEST_common.c:310
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:2894
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
void statevec_controlledPauliYLocal(Qureg qureg, const int controlQubit, const int targetQubit, const int conjFac)
Definition: QuEST_cpu.c:2740
void densmatr_mixDampingDistributed(Qureg qureg, const int targetQubit, qreal damping)
Definition: QuEST_cpu.c:299
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.
qreal statevec_getRealAmp(Qureg qureg, long long int index)
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1070
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
void statevec_compactUnitary(Qureg qureg, const int targetQubit, Complex alpha, Complex beta)
void zeroSomeAmps(Qureg qureg, long long int startInd, long long int numAmps)
Definition: QuEST_cpu.c:733
void densmatr_oneQubitDegradeOffDiagonal(Qureg qureg, const int targetQubit, qreal retain)
Definition: QuEST_cpu.c:48
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:989