diff --git a/.clang-format b/.clang-format index 0a92d2ebf..2bc78d779 100644 --- a/.clang-format +++ b/.clang-format @@ -8,7 +8,7 @@ AlignConsecutiveDeclarations: false AlignEscapedNewlines: Right AlignOperands: false AlignTrailingComments: false -AllowAllParametersOfDeclarationOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All @@ -35,7 +35,7 @@ BraceWrapping: SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true -BreakBeforeBinaryOperators: All +BreakBeforeBinaryOperators: None BreakBeforeBraces: WebKit BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: true @@ -53,7 +53,7 @@ Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: false +FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH diff --git a/complex16simd.cpp b/complex16simd.cpp index 0071e6ec3..a641e2732 100644 --- a/complex16simd.cpp +++ b/complex16simd.cpp @@ -114,4 +114,4 @@ Complex16Simd polar(const double rho, const double theta = 0) { return Complex16Simd(_mm_set1_pd(rho) * _mm_set_pd(cos(theta), sin(theta))); } -} +} // namespace Qrack diff --git a/complex16simd.hpp b/complex16simd.hpp index d7a6322d1..a0b036832 100644 --- a/complex16simd.hpp +++ b/complex16simd.hpp @@ -45,4 +45,4 @@ Complex16Simd conj(const Complex16Simd& cmplx); double norm(const Complex16Simd& cmplx); double abs(const Complex16Simd& cmplx); Complex16Simd polar(const double rho, const double theta); -} +} // namespace Qrack diff --git a/par_for.cpp b/par_for.cpp index 5d60b1bfd..7a229daba 100644 --- a/par_for.cpp +++ b/par_for.cpp @@ -70,4 +70,4 @@ double par_norm(const bitCapInt maxQPower, const Complex16* stateArray) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // THIS ENDS THE EXCERPTED SECTION FROM "GILGAMESH." //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -} +} // namespace Qrack diff --git a/par_for.hpp b/par_for.hpp index 6fc18359c..2ea5776f6 100644 --- a/par_for.hpp +++ b/par_for.hpp @@ -116,21 +116,21 @@ void par_for_skip(const bitCapInt begin, const bitCapInt end, const bitCapInt sk int num_cpus = std::thread::hardware_concurrency(); std::vector> futures(num_cpus); for (int cpu = 0; cpu != num_cpus; ++cpu) { - futures[cpu] - = std::async(std::launch::async, [cpu, &idx, end, skipPower, stateArray, bciArgs, nStateVec, &fn]() { - bitCapInt i, iLow, iHigh; - for (;;) { - iHigh = idx++; - i = 0; - iLow = iHigh % skipPower; - i += iLow; - iHigh = (iHigh - iLow) << 1; - i += iHigh; - if (i >= end) - break; - fn(i, cpu, stateArray, bciArgs, nStateVec); - } - }); + futures[cpu] = + std::async(std::launch::async, [cpu, &idx, end, skipPower, stateArray, bciArgs, nStateVec, &fn]() { + bitCapInt i, iLow, iHigh; + for (;;) { + iHigh = idx++; + i = 0; + iLow = iHigh % skipPower; + i += iLow; + iHigh = (iHigh - iLow) << 1; + i += iHigh; + if (i >= end) + break; + fn(i, cpu, stateArray, bciArgs, nStateVec); + } + }); } for (int cpu = 0; cpu != num_cpus; ++cpu) { diff --git a/qregister.cpp b/qregister.cpp index bd2662981..c267d92a5 100644 --- a/qregister.cpp +++ b/qregister.cpp @@ -42,8 +42,8 @@ void rotate(BidirectionalIterator first, BidirectionalIterator middle, Bidirecti * opcodes-like methods. */ -/// Initialize a coherent unit with qBitCount number of bits, all to |0> state. -CoherentUnit::CoherentUnit(bitLenInt qBitCount) +/// Initialize a coherent unit with qBitCount number pf bits, to initState unsigned integer permutation state +CoherentUnit::CoherentUnit(bitLenInt qBitCount, bitCapInt initState) : rand_distribution(0.0, 1.0) { if (qBitCount > (sizeof(bitCapInt) * bitsInByte)) @@ -60,24 +60,13 @@ CoherentUnit::CoherentUnit(bitLenInt qBitCount) stateVec.reset(); stateVec = std::move(sv); std::fill(&(stateVec[0]), &(stateVec[0]) + maxQPower, Complex16(0.0, 0.0)); - stateVec[0] = Complex16(cos(angle), sin(angle)); + stateVec[initState] = Complex16(cos(angle), sin(angle)); } -/// Initialize a coherent unit with qBitCount number pf bits, to initState unsigned integer permutation state -CoherentUnit::CoherentUnit(bitLenInt qBitCount, bitCapInt initState) - : rand_distribution(0.0, 1.0) +/// Initialize a coherent unit with qBitCount number of bits, all to |0> state. +CoherentUnit::CoherentUnit(bitLenInt qBitCount) + : CoherentUnit(qBitCount, 0) { - rand_generator.seed(std::time(0)); - - double angle = Rand() * 2.0 * M_PI; - runningNorm = 1.0; - qubitCount = qBitCount; - maxQPower = 1 << qBitCount; - std::unique_ptr sv(new Complex16[maxQPower]); - stateVec.reset(); - stateVec = std::move(sv); - std::fill(&(stateVec[0]), &(stateVec[0]) + maxQPower, Complex16(0.0, 0.0)); - stateVec[initState] = Complex16(cos(angle), sin(angle)); } /// PSEUDO-QUANTUM Initialize a cloned register with same exact quantum state as pqs @@ -89,19 +78,22 @@ CoherentUnit::CoherentUnit(const CoherentUnit& pqs) runningNorm = pqs.runningNorm; qubitCount = pqs.qubitCount; maxQPower = pqs.maxQPower; + std::unique_ptr sv(new Complex16[maxQPower]); stateVec.reset(); stateVec = std::move(sv); - std::copy(&(pqs.stateVec[0]), &(pqs.stateVec[0]) + maxQPower, &(stateVec[0])); + SetQuantumState(pqs.stateVec); } /// Get the count of bits in this register int CoherentUnit::GetQubitCount() { return qubitCount; } + /// PSEUDO-QUANTUM Output the exact quantum state of this register as a permutation basis array of complex numbers void CoherentUnit::CloneRawState(Complex16* output) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } std::copy(&(stateVec[0]), &(stateVec[0]) + maxQPower, &(output[0])); } @@ -123,53 +115,69 @@ void CoherentUnit::SetPermutation(bitCapInt perm) std::fill(&(stateVec[0]), &(stateVec[0]) + maxQPower, Complex16(0.0, 0.0)); stateVec[perm] = Complex16(cos(angle), sin(angle)); } + /// Set arbitrary pure quantum state, in unsigned int permutation basis void CoherentUnit::SetQuantumState(Complex16* inputState) { std::copy(&(inputState[0]), &(inputState[0]) + maxQPower, &(stateVec[0])); } -/// Combine (a copy of) another CoherentUnit with this one, after the last bit index of this one. -/** Combine (a copy of) another CoherentUnit with this one, after the last bit index of this one. (If the programmer - * doesn't want to "cheat," it is left up to them to delete the old coherent unit that was added. */ + +/** + * Combine (a copy of) another CoherentUnit with this one, after the last bit + * index of this one. (If the programmer doesn't want to "cheat," it is left up + * to them to delete the old coherent unit that was added. + */ void CoherentUnit::Cohere(CoherentUnit& toCopy) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); - if (toCopy.runningNorm != 1.0) + } + + if (toCopy.runningNorm != 1.0) { toCopy.NormalizeState(); + } bitCapInt i; bitCapInt nQubitCount = qubitCount + toCopy.qubitCount; bitCapInt nMaxQPower = 1 << nQubitCount; bitCapInt startMask = 0; bitCapInt endMask = 0; + for (i = 0; i < qubitCount; i++) { startMask += (1 << i); } + for (i = qubitCount; i < nQubitCount; i++) { endMask += (1 << i); } + double angle = Rand() * 2.0 * M_PI; Complex16 phaseFac(cos(angle), sin(angle)); std::unique_ptr nStateVec(new Complex16[nMaxQPower]); for (i = 0; i < nMaxQPower; i++) { - nStateVec[i] - = phaseFac * sqrt(norm(stateVec[(i & startMask)]) * norm(toCopy.stateVec[((i & endMask) >> qubitCount)])); + nStateVec[i] = + phaseFac * sqrt(norm(stateVec[(i & startMask)]) * norm(toCopy.stateVec[((i & endMask) >> qubitCount)])); } + qubitCount = nQubitCount; maxQPower = 1 << nQubitCount; - ResetStateVec(nStateVec); + ResetStateVec(nStateVec); UpdateRunningNorm(); } -/// Minimally decohere a set of contigious bits from the full coherent unit. -/** Minimally decohere a set of contigious bits from the full coherent unit. The length of this coherent unit is reduced - * by the length of bits decohered, and the bits removed are output in the destination CoherentUnit pointer. The - * destination object must be initialized to the correct number of bits, in 0 permutation state. */ + +/** + * Minimally decohere a set of contigious bits from the full coherent unit. The + * length of this coherent unit is reduced by the length of bits decohered, and + * the bits removed are output in the destination CoherentUnit pointer. The + * destination object must be initialized to the correct number of bits, in 0 + * permutation state. + */ void CoherentUnit::Decohere(bitLenInt start, bitLenInt length, CoherentUnit& destination) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } bitLenInt end = start + length; bitCapInt mask = 0; @@ -178,6 +186,7 @@ void CoherentUnit::Decohere(bitLenInt start, bitLenInt length, CoherentUnit& des bitCapInt partPower = 1 << length; bitCapInt remainderPower = 1 << (qubitCount - length); bitCapInt i; + for (i = start; i < end; i++) { mask += (1 << i); } @@ -191,22 +200,27 @@ void CoherentUnit::Decohere(bitLenInt start, bitLenInt length, CoherentUnit& des std::unique_ptr partStateProb(new double[partPower]()); std::unique_ptr remainderStateProb(new double[remainderPower]()); double prob; + for (i = 0; i < maxQPower; i++) { prob = norm(stateVec[i]); partStateProb[(i & mask) >> start] += prob; remainderStateProb[(i & startMask) + ((i & endMask) >> length)] += prob; } + qubitCount = qubitCount - length; maxQPower = 1 << qubitCount; + std::unique_ptr sv(new Complex16[remainderPower]()); ResetStateVec(sv); double angle = Rand() * 2.0 * M_PI; Complex16 phaseFac(cos(angle), sin(angle)); double totProb = 0.0; + for (i = 0; i < partPower; i++) { totProb += partStateProb[i]; } + if (totProb == 0.0) { destination.stateVec[0] = phaseFac; } else { @@ -218,9 +232,11 @@ void CoherentUnit::Decohere(bitLenInt start, bitLenInt length, CoherentUnit& des angle = Rand() * 2.0 * M_PI; phaseFac = Complex16(cos(angle), sin(angle)); totProb = 0.0; + for (i = 0; i < remainderPower; i++) { totProb += remainderStateProb[i]; } + if (totProb == 0.0) { stateVec[0] = phaseFac; } else { @@ -235,14 +251,16 @@ void CoherentUnit::Decohere(bitLenInt start, bitLenInt length, CoherentUnit& des void CoherentUnit::Dispose(bitLenInt start, bitLenInt length) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } bitLenInt end = start + length; bitCapInt startMask = 0; bitCapInt endMask = 0; bitCapInt remainderPower = 1 << (qubitCount - length); bitCapInt i; + for (i = 0; i < start; i++) { startMask += (1 << i); } @@ -256,12 +274,14 @@ void CoherentUnit::Dispose(bitLenInt start, bitLenInt length) } qubitCount = qubitCount - length; maxQPower = 1 << qubitCount; + std::unique_ptr sv(new Complex16[remainderPower]()); ResetStateVec(sv); double angle = Rand() * 2.0 * M_PI; Complex16 phaseFac(cos(angle), sin(angle)); double totProb = 0.0; + for (i = 0; i < remainderPower; i++) { totProb += remainderStateProb[i]; } @@ -277,27 +297,32 @@ void CoherentUnit::Dispose(bitLenInt start, bitLenInt length) } // Logic Gates: -///"AND" compare two bits in CoherentUnit, and store result in outputBit + +/// "AND" compare two bits in CoherentUnit, and store result in outputBit void CoherentUnit::AND(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit) { - if (!((inputBit1 == inputBit2) && (inputBit2 == outputBit))) { - if ((inputBit1 == outputBit) || (inputBit2 == outputBit)) { - CoherentUnit extraBit(1, 0); - Cohere(extraBit); - CCNOT(inputBit1, inputBit2, qubitCount - 1); - Swap(qubitCount - 1, outputBit); - Dispose(qubitCount - 1, 1); + /* Same bit, no action necessary. */ + if ((inputBit1 == inputBit2) && (inputBit2 == outputBit)) { + return; + } + + if ((inputBit1 == outputBit) || (inputBit2 == outputBit)) { + CoherentUnit extraBit(1, 0); + Cohere(extraBit); + CCNOT(inputBit1, inputBit2, qubitCount - 1); + Swap(qubitCount - 1, outputBit); + Dispose(qubitCount - 1, 1); + } else { + SetBit(outputBit, false); + if (inputBit1 == inputBit2) { + CNOT(inputBit1, outputBit); } else { - SetBit(outputBit, false); - if (inputBit1 == inputBit2) { - CNOT(inputBit1, outputBit); - } else { - CCNOT(inputBit1, inputBit2, outputBit); - } + CCNOT(inputBit1, inputBit2, outputBit); } } } -///"AND" compare a qubit in CoherentUnit with a classical bit, and store result in outputBit + +/// "AND" compare a qubit in CoherentUnit with a classical bit, and store result in outputBit void CoherentUnit::CLAND(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit) { if (!inputClassicalBit) { @@ -307,27 +332,32 @@ void CoherentUnit::CLAND(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt CNOT(inputQBit, outputBit); } } -///"OR" compare two bits in CoherentUnit, and store result in outputBit + +/// "OR" compare two bits in CoherentUnit, and store result in outputBit void CoherentUnit::OR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit) { - if (!((inputBit1 == inputBit2) && (inputBit2 == outputBit))) { - if ((inputBit1 == outputBit) || (inputBit2 == outputBit)) { - CoherentUnit extraBit(1, 1); - Cohere(extraBit); - AntiCCNOT(inputBit1, inputBit2, qubitCount - 1); - Swap(qubitCount - 1, outputBit); - Dispose(qubitCount - 1, 1); + /* Same bit, no action necessary. */ + if ((inputBit1 == inputBit2) && (inputBit2 == outputBit)) { + return; + } + + if ((inputBit1 == outputBit) || (inputBit2 == outputBit)) { + CoherentUnit extraBit(1, 1); + Cohere(extraBit); + AntiCCNOT(inputBit1, inputBit2, qubitCount - 1); + Swap(qubitCount - 1, outputBit); + Dispose(qubitCount - 1, 1); + } else { + SetBit(outputBit, true); + if (inputBit1 == inputBit2) { + AntiCNOT(inputBit1, outputBit); } else { - SetBit(outputBit, true); - if (inputBit1 == inputBit2) { - AntiCNOT(inputBit1, outputBit); - } else { - AntiCCNOT(inputBit1, inputBit2, outputBit); - } + AntiCCNOT(inputBit1, inputBit2, outputBit); } } } -///"OR" compare a qubit in CoherentUnit with a classical bit, and store result in outputBit + +/// "OR" compare a qubit in CoherentUnit with a classical bit, and store result in outputBit void CoherentUnit::CLOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit) { if (inputClassicalBit) { @@ -337,27 +367,30 @@ void CoherentUnit::CLOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt o CNOT(inputQBit, outputBit); } } -///"XOR" compare two bits in CoherentUnit, and store result in outputBit + +/// "XOR" compare two bits in CoherentUnit, and store result in outputBit void CoherentUnit::XOR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit) { if (((inputBit1 == inputBit2) && (inputBit2 == outputBit))) { SetBit(outputBit, false); + return; + } + + if ((inputBit1 == outputBit) || (inputBit2 == outputBit)) { + CoherentUnit extraBit(1, 0); + Cohere(extraBit); + CNOT(inputBit1, qubitCount - 1); + CNOT(inputBit2, qubitCount - 1); + Swap(qubitCount - 1, outputBit); + Dispose(qubitCount - 1, 1); } else { - if ((inputBit1 == outputBit) || (inputBit2 == outputBit)) { - CoherentUnit extraBit(1, 0); - Cohere(extraBit); - CNOT(inputBit1, qubitCount - 1); - CNOT(inputBit2, qubitCount - 1); - Swap(qubitCount - 1, outputBit); - Dispose(qubitCount - 1, 1); - } else { - SetBit(outputBit, false); - CNOT(inputBit1, outputBit); - CNOT(inputBit2, outputBit); - } + SetBit(outputBit, false); + CNOT(inputBit1, outputBit); + CNOT(inputBit2, outputBit); } } -///"XOR" compare a qubit in CoherentUnit with a classical bit, and store result in outputBit + +/// "XOR" compare a qubit in CoherentUnit with a classical bit, and store result in outputBit void CoherentUnit::CLXOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit) { if (inputQBit != outputBit) { @@ -367,15 +400,19 @@ void CoherentUnit::CLXOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt X(outputBit); } } + /// Doubly-controlled not void CoherentUnit::CCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target) { // if ((control1 >= qubitCount) || (control2 >= qubitCount)) // throw std::invalid_argument("CCNOT tried to operate on bit index greater than total bits."); - if (control1 == control2) + if (control1 == control2) { throw std::invalid_argument("CCNOT control bits cannot be same bit."); - if (control1 == target || control2 == target) + } + + if (control1 == target || control2 == target) { throw std::invalid_argument("CCNOT control bits cannot also be target."); + } const Complex16 pauliX[4] = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), Complex16(0.0, 0.0) }; @@ -391,15 +428,18 @@ void CoherentUnit::CCNOT(bitLenInt control1, bitLenInt control2, bitLenInt targe std::sort(qPowersSorted, qPowersSorted + 3); Apply2x2(qPowers[0], qPowers[1] + qPowers[2], pauliX, 3, qPowersSorted, false, false); } + /// "Anti-doubly-controlled not" - Apply "not" if control bits are both zero, do not apply if either control bit is one. void CoherentUnit::AntiCCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target) { // if ((control1 >= qubitCount) || (control2 >= qubitCount)) // throw std::invalid_argument("CCNOT tried to operate on bit index greater than total bits."); - if (control1 == control2) + if (control1 == control2) { throw std::invalid_argument("CCNOT control bits cannot be same bit."); - if (control1 == target || control2 == target) + } + if (control1 == target || control2 == target) { throw std::invalid_argument("CCNOT control bits cannot also be target."); + } const Complex16 pauliX[4] = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), Complex16(0.0, 0.0) }; @@ -415,40 +455,49 @@ void CoherentUnit::AntiCCNOT(bitLenInt control1, bitLenInt control2, bitLenInt t std::sort(qPowersSorted, qPowersSorted + 3); Apply2x2(0, qPowers[3], pauliX, 3, qPowersSorted, false, false); } + /// Controlled not void CoherentUnit::CNOT(bitLenInt control, bitLenInt target) { // if ((control >= qubitCount) || (target >= qubitCount)) // throw std::invalid_argument("CNOT tried to operate on bit index greater than total bits."); - if (control == target) + if (control == target) { throw std::invalid_argument("CNOT control bit cannot also be target."); + } + const Complex16 pauliX[4] = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), Complex16(0.0, 0.0) }; ApplyControlled2x2(control, target, pauliX, false); } -///"Anti-controlled not" - Apply "not" if control bit is zero, do not apply if control bit is one. + +/// "Anti-controlled not" - Apply "not" if control bit is zero, do not apply if control bit is one. void CoherentUnit::AntiCNOT(bitLenInt control, bitLenInt target) { // if ((control >= qubitCount) || (target >= qubitCount)) // throw std::invalid_argument("CNOT tried to operate on bit index greater than total bits."); - if (control == target) + if (control == target) { throw std::invalid_argument("CNOT control bit cannot also be target."); + } + const Complex16 pauliX[4] = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), Complex16(0.0, 0.0) }; ApplyAntiControlled2x2(control, target, pauliX, false); } + /// Hadamard gate void CoherentUnit::H(bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("H tried to operate on bit index greater than total + // if (qubitIndex >= qubitCount) throw std::invalid_argument("operation on bit index greater than total // bits."); const Complex16 had[4] = { Complex16(1.0 / M_SQRT2, 0.0), Complex16(1.0 / M_SQRT2, 0.0), Complex16(1.0 / M_SQRT2, 0.0), Complex16(-1.0 / M_SQRT2, 0.0) }; ApplySingleBit(qubitIndex, had, true); } + /// Measurement gate bool CoherentUnit::M(bitLenInt qubitIndex) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } bool result; double prob = Rand(); @@ -463,8 +512,10 @@ bool CoherentUnit::M(bitLenInt qubitIndex) result = (prob < oneChance) && oneChance > 0.0; double nrmlzr = 1.0; if (result) { - if (oneChance > 0.0) + if (oneChance > 0.0) { nrmlzr = oneChance; + } + par_for_all(0, maxQPower, &(stateVec[0]), Complex16(cosine, sine) / nrmlzr, NULL, qPowers, [](const bitCapInt lcv, const int cpu, Complex16* stateVec, const Complex16 nrm, const Complex16* mtrx, const bitCapInt* qPowers) { @@ -475,8 +526,10 @@ bool CoherentUnit::M(bitLenInt qubitIndex) } }); } else { - if (oneChance < 1.0) + if (oneChance < 1.0) { nrmlzr = sqrt(1.0 - oneChance); + } + par_for_all(0, maxQPower, &(stateVec[0]), Complex16(cosine, sine) / nrmlzr, NULL, qPowers, [](const bitCapInt lcv, const int cpu, Complex16* stateVec, const Complex16 nrm, const Complex16* mtrx, const bitCapInt* qPowers) { @@ -492,15 +545,18 @@ bool CoherentUnit::M(bitLenInt qubitIndex) return result; } + /// PSEUDO-QUANTUM Direct measure of bit probability to be in |1> state double CoherentUnit::Prob(bitLenInt qubitIndex) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } bitCapInt qPower = 1 << qubitIndex; double oneChance = 0; bitCapInt lcv; + for (lcv = 0; lcv < maxQPower; lcv++) { if ((lcv & qPower) == qPower) { oneChance += norm(stateVec[lcv]); @@ -509,104 +565,132 @@ double CoherentUnit::Prob(bitLenInt qubitIndex) return oneChance; } + /// PSEUDO-QUANTUM Direct measure of full register probability to be in permutation state double CoherentUnit::ProbAll(bitCapInt fullRegister) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } return norm(stateVec[fullRegister]); } + /// PSEUDO-QUANTUM Direct measure of all bit probabilities in register to be in |1> state void CoherentUnit::ProbArray(double* probArray) { - if (runningNorm != 1.0) + if (runningNorm != 1.0) { NormalizeState(); + } bitCapInt lcv; for (lcv = 0; lcv < maxQPower; lcv++) { probArray[lcv] = norm(stateVec[lcv]); } } -///"Phase shift gate" - Rotates as e^(-i*\theta/2) around |1> state + +/// "Phase shift gate" - Rotates as e^(-i*\theta/2) around |1> state void CoherentUnit::R1(double radians, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total // bits."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); const Complex16 mtrx[4] = { Complex16(1.0, 0), Complex16(0.0, 0.0), Complex16(0.0, 0.0), Complex16(cosine, sine) }; ApplySingleBit(qubitIndex, mtrx, true); } -/// Dyadic fraction "phase shift gate" - Rotates as e^(i*(M_PI * numerator) / denominator) around |1> state -/** Dyadic fraction "phase shift gate" - Rotates as e^(i*(M_PI * numerator) / denominator) around |1> state. NOTE THAT - * DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. */ + +/** + * Dyadic fraction "phase shift gate" - Rotates as e^(i*(M_PI * numerator) / + * denominator) around |1> state. + * + * NOTE THAT * DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. + */ void CoherentUnit::R1Dyad(int numerator, int denominator, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); R1((M_PI * numerator * 2) / denominator, qubitIndex); } + /// x axis rotation gate - Rotates as e^(-i*\theta/2) around Pauli x axis void CoherentUnit::RX(double radians, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("X tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); - Complex16 pauliRX[4] - = { Complex16(cosine, 0.0), Complex16(0.0, -sine), Complex16(0.0, -sine), Complex16(cosine, 0.0) }; + Complex16 pauliRX[4] = { Complex16(cosine, 0.0), Complex16(0.0, -sine), Complex16(0.0, -sine), + Complex16(cosine, 0.0) }; ApplySingleBit(qubitIndex, pauliRX, true); } -/// Dyadic fraction x axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli x axis -/** Dyadic fraction x axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli x axis. NOTE - * THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. */ + +/** + * Dyadic fraction x axis rotation gate - Rotates as e^(i*(M_PI * numerator) / + * denominator) around Pauli x axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. + */ void CoherentUnit::RXDyad(int numerator, int denominator, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); RX((-M_PI * numerator * 2) / denominator, qubitIndex); } + /// y axis rotation gate - Rotates as e^(-i*\theta/2) around Pauli y axis void CoherentUnit::RY(double radians, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Y tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); - Complex16 pauliRY[4] - = { Complex16(cosine, 0.0), Complex16(-sine, 0.0), Complex16(sine, 0.0), Complex16(cosine, 0.0) }; + Complex16 pauliRY[4] = { Complex16(cosine, 0.0), Complex16(-sine, 0.0), Complex16(sine, 0.0), + Complex16(cosine, 0.0) }; ApplySingleBit(qubitIndex, pauliRY, true); } -/// Dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y axis -/** Dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y axis. NOTE - * THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. */ + +/** + * Dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / + * denominator) around Pauli y axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. + */ void CoherentUnit::RYDyad(int numerator, int denominator, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); RY((-M_PI * numerator * 2) / denominator, qubitIndex); } + /// z axis rotation gate - Rotates as e^(-i*\theta/2) around Pauli z axis void CoherentUnit::RZ(double radians, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); - const Complex16 pauliRZ[4] - = { Complex16(cosine, -sine), Complex16(0.0, 0.0), Complex16(0.0, 0.0), Complex16(cosine, sine) }; + const Complex16 pauliRZ[4] = { Complex16(cosine, -sine), Complex16(0.0, 0.0), Complex16(0.0, 0.0), + Complex16(cosine, sine) }; ApplySingleBit(qubitIndex, pauliRZ, true); } -/// Dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y axis -/** Dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y axis. NOTE - * THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. */ + +/** + * Dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS AND LACKS DIVISION BY A FACTOR OF TWO. + */ void CoherentUnit::RZDyad(int numerator, int denominator, bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); RZ((-M_PI * numerator * 2) / denominator, qubitIndex); } + /// Set individual bit to pure |0> (false) or |1> (true) state void CoherentUnit::SetBit(bitLenInt qubitIndex1, bool value) { @@ -614,14 +698,15 @@ void CoherentUnit::SetBit(bitLenInt qubitIndex1, bool value) X(qubitIndex1); } } + /// Swap values of two bits in register void CoherentUnit::Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2) { // if ((qubitIndex1 >= qubitCount) || (qubitIndex2 >= qubitCount)) - // throw std::invalid_argument("CNOT tried to operate on bit index greater than total bits."); + // throw std::invalid_argument("operation on bit index greater than total bits."); if (qubitIndex1 != qubitIndex2) { - const Complex16 pauliX[4] - = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), Complex16(0.0, 0.0) }; + const Complex16 pauliX[4] = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), + Complex16(0.0, 0.0) }; bitCapInt qPowers[3]; bitCapInt qPowersSorted[2]; @@ -639,131 +724,145 @@ void CoherentUnit::Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2) Apply2x2(qPowers[2], qPowers[1], pauliX, 2, qPowersSorted, false, false); } } + /// NOT gate, which is also Pauli x matrix void CoherentUnit::X(bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("X tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); const Complex16 pauliX[4] = { Complex16(0.0, 0.0), Complex16(1.0, 0.0), Complex16(1.0, 0.0), Complex16(0.0, 0.0) }; ApplySingleBit(qubitIndex, pauliX, false); } + /// Apply Pauli Y matrix to bit void CoherentUnit::Y(bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Y tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); const Complex16 pauliY[4] = { Complex16(0.0, 0.0), Complex16(0.0, -1.0), Complex16(0.0, 1.0), Complex16(0.0, 0.0) }; ApplySingleBit(qubitIndex, pauliY, false); } + /// Apply Pauli Z matrix to bit void CoherentUnit::Z(bitLenInt qubitIndex) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (qubitIndex >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); const Complex16 pauliZ[4] = { Complex16(1.0, 0.0), Complex16(0.0, 0.0), Complex16(0.0, 0.0), Complex16(-1.0, 0.0) }; ApplySingleBit(qubitIndex, pauliZ, false); } -/// Controlled "phase shift gate" -/** Controlled "phase shift gate" - if control bit is true, rotates target bit as e^(-i*\theta/2) around |1> state */ + +/// Controlled "phase shift gate" - if control bit is true, rotates target bit as e^(-i*\theta/2) around |1> state void CoherentUnit::CRT(double radians, bitLenInt control, bitLenInt target) { // if ((control >= qubitCount) || (target >= qubitCount)) - // throw std::invalid_argument("CNOT tried to operate on bit index greater than total bits."); - if (control == target) - throw std::invalid_argument("CRT control bit cannot also be target."); + // throw std::invalid_argument("operation on bit index greater than total bits."); + if (control == target) { + throw std::invalid_argument("control bit cannot also be target."); + } + double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); const Complex16 mtrx[4] = { Complex16(1.0, 0), Complex16(0.0, 0.0), Complex16(0.0, 0.0), Complex16(cosine, sine) }; ApplyControlled2x2(control, target, mtrx, true); } -/// Controlled dyadic fraction "phase shift gate" -/** Controlled "phase shift gate" - if control bit is true, rotates target bit as e^(-i*\theta/2) around |1> state */ + +/// Controlled "phase shift gate" - if control bit is true, rotates target bit as e^(-i*\theta/2) around |1> state void CoherentUnit::CRTDyad(int numerator, int denominator, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (control >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); + // if (target >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); if (control == target) throw std::invalid_argument("CRTDyad control bit cannot also be target."); CRT((-M_PI * numerator * 2) / denominator, control, target); } -/// Controlled x axis rotation -/** Controlled x axis rotation - if control bit is true, rotates as e^(-i*\theta/2) around Pauli x axis */ + +/// Controlled x axis rotation - if control bit is true, rotates as e^(-i*\theta/2) around Pauli x axis void CoherentUnit::CRX(double radians, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("X tried to operate on bit index greater than total - // bits."); + // if (control >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); if (control == target) throw std::invalid_argument("CRX control bit cannot also be target."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); - Complex16 pauliRX[4] - = { Complex16(cosine, 0.0), Complex16(0.0, -sine), Complex16(0.0, -sine), Complex16(cosine, 0.0) }; + Complex16 pauliRX[4] = { Complex16(cosine, 0.0), Complex16(0.0, -sine), Complex16(0.0, -sine), + Complex16(cosine, 0.0) }; ApplyControlled2x2(control, target, pauliRX, true); } -/// Controlled dyadic fraction x axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli x -/// axis -/** Controlled dyadic fraction x axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli x - * axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS. */ + +/** + * Controlled dyadic fraction x axis rotation gate - Rotates as e^(i*(M_PI * + * numerator) / denominator) around Pauli x axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS. + */ void CoherentUnit::CRXDyad(int numerator, int denominator, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); + // if (control >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); if (control == target) throw std::invalid_argument("CRXDyad control bit cannot also be target."); CRX((-M_PI * numerator * 2) / denominator, control, target); } -/// Controlled y axis rotation -/** Controlled y axis rotation - if control bit is true, rotates as e^(-i*\theta) around Pauli y axis */ + +/// Controlled y axis rotation - if control bit is true, rotates as e^(-i*\theta) around Pauli y axis void CoherentUnit::CRY(double radians, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Y tried to operate on bit index greater than total - // bits."); + // if (control >= qubitCount) + // throw std::invalid_argument("operation on bit index greater than total bits."); if (control == target) throw std::invalid_argument("CRY control bit cannot also be target."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); - Complex16 pauliRY[4] - = { Complex16(cosine, 0.0), Complex16(-sine, 0.0), Complex16(sine, 0.0), Complex16(cosine, 0.0) }; + Complex16 pauliRY[4] = { Complex16(cosine, 0.0), Complex16(-sine, 0.0), Complex16(sine, 0.0), + Complex16(cosine, 0.0) }; ApplyControlled2x2(control, target, pauliRY, true); } -/// Controlled dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y -/// axis -/** Controlled dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y - * axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS. */ + +/** + * Controlled dyadic fraction y axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli y + * axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS. + */ void CoherentUnit::CRYDyad(int numerator, int denominator, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); if (control == target) throw std::invalid_argument("CRYDyad control bit cannot also be target."); CRY((-M_PI * numerator * 2) / denominator, control, target); } -/// Controlled z axis rotation -/** Controlled z axis rotation - if control bit is true, rotates as e^(-i*\theta) around Pauli z axis */ + +/// Controlled z axis rotation - if control bit is true, rotates as e^(-i*\theta) around Pauli z axis void CoherentUnit::CRZ(double radians, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); if (control == target) throw std::invalid_argument("CRZ control bit cannot also be target."); double cosine = cos(radians / 2.0); double sine = sin(radians / 2.0); - const Complex16 pauliRZ[4] - = { Complex16(cosine, -sine), Complex16(0.0, 0.0), Complex16(0.0, 0.0), Complex16(cosine, sine) }; + const Complex16 pauliRZ[4] = { Complex16(cosine, -sine), Complex16(0.0, 0.0), Complex16(0.0, 0.0), + Complex16(cosine, sine) }; ApplyControlled2x2(control, target, pauliRZ, true); } -/// Controlled dyadic fraction z axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli z -/// axis -/** Controlled dyadic fraction z axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli z - * axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS. */ + +/** + * Controlled dyadic fraction z axis rotation gate - Rotates as e^(i*(M_PI * numerator) / denominator) around Pauli z + * axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION + * OPERATORS. + */ void CoherentUnit::CRZDyad(int numerator, int denominator, bitLenInt control, bitLenInt target) { - // if (qubitIndex >= qubitCount) throw std::invalid_argument("Z tried to operate on bit index greater than total - // bits."); if (control == target) throw std::invalid_argument("CRZDyad control bit cannot also be target."); CRZ((-M_PI * numerator * 2) / denominator, control, target); } + /// Apply controlled Pauli Y matrix to bit void CoherentUnit::CY(bitLenInt control, bitLenInt target) { @@ -774,6 +873,7 @@ void CoherentUnit::CY(bitLenInt control, bitLenInt target) const Complex16 pauliY[4] = { Complex16(0.0, 0.0), Complex16(0.0, -1.0), Complex16(0.0, 1.0), Complex16(0.0, 0.0) }; ApplyControlled2x2(control, target, pauliY, false); } + /// Apply controlled Pauli Z matrix to bit void CoherentUnit::CZ(bitLenInt control, bitLenInt target) { @@ -786,6 +886,7 @@ void CoherentUnit::CZ(bitLenInt control, bitLenInt target) } // Single register instructions: + /// Apply X ("not") gate to each bit in "length," starting from bit index "start" void CoherentUnit::X(bitLenInt start, bitLenInt length) { @@ -806,6 +907,7 @@ void CoherentUnit::X(bitLenInt start, bitLenInt length) }); ResetStateVec(nStateVec); } + /// Apply Hadamard gate to each bit in "length," starting from bit index "start" void CoherentUnit::H(bitLenInt start, bitLenInt length) { @@ -813,6 +915,7 @@ void CoherentUnit::H(bitLenInt start, bitLenInt length) H(start + lcv); } } + ///"Phase shift gate" - Rotates each bit as e^(-i*\theta/2) around |1> state void CoherentUnit::R1(double radians, bitLenInt start, bitLenInt length) { @@ -820,16 +923,20 @@ void CoherentUnit::R1(double radians, bitLenInt start, bitLenInt length) R1(radians, start + lcv); } } -/// Dyadic fraction "phase shift gate" - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around |1> state -/** Dyadic fraction "phase shift gate" - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around |1> state. + +/** + * Dyadic fraction "phase shift gate" - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around |1> state. + * * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR OF - * TWO. */ + * TWO. + */ void CoherentUnit::R1Dyad(int numerator, int denominator, bitLenInt start, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { R1Dyad(numerator, denominator, start + lcv); } } + /// x axis rotation gate - Rotates each bit as e^(-i*\theta/2) around Pauli x axis void CoherentUnit::RX(double radians, bitLenInt start, bitLenInt length) { @@ -837,17 +944,21 @@ void CoherentUnit::RX(double radians, bitLenInt start, bitLenInt length) RX(radians, start + lcv); } } -/// Dyadic fraction x axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli x -/// axis -/** Dyadic fraction x axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli x - * axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR - * OF TWO. */ + +/** + * Dyadic fraction x axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli x + * axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR + * OF TWO. + */ void CoherentUnit::RXDyad(int numerator, int denominator, bitLenInt start, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { RXDyad(numerator, denominator, start + lcv); } } + /// y axis rotation gate - Rotates each bit as e^(-i*\theta/2) around Pauli y axis void CoherentUnit::RY(double radians, bitLenInt start, bitLenInt length) { @@ -855,17 +966,21 @@ void CoherentUnit::RY(double radians, bitLenInt start, bitLenInt length) RY(radians, start + lcv); } } -/// Dyadic fraction y axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli y -/// axis -/** Dyadic fraction y axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli y - * axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR - * OF TWO. */ + +/** + * Dyadic fraction y axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli y + * axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR + * OF TWO. + */ void CoherentUnit::RYDyad(int numerator, int denominator, bitLenInt start, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { RYDyad(numerator, denominator, start + lcv); } } + /// z axis rotation gate - Rotates each bit as e^(-i*\theta/2) around Pauli z axis void CoherentUnit::RZ(double radians, bitLenInt start, bitLenInt length) { @@ -873,17 +988,21 @@ void CoherentUnit::RZ(double radians, bitLenInt start, bitLenInt length) RZ(radians, start + lcv); } } -/// Dyadic fraction z axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli y -/// axis -/** Dyadic fraction z axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli y - * axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR - * OF TWO. */ + +/** + * Dyadic fraction z axis rotation gate - Rotates each bit as e^(i*(M_PI * numerator) / denominator) around Pauli y + * axis. + * + * NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM RADIAN ROTATION OPERATORS AND LACKS DIVISION BY A FACTOR + * OF TWO. + */ void CoherentUnit::RZDyad(int numerator, int denominator, bitLenInt start, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { RZDyad(numerator, denominator, start + lcv); } } + /// Apply Pauli Y matrix to each bit void CoherentUnit::Y(bitLenInt start, bitLenInt length) { @@ -891,6 +1010,7 @@ void CoherentUnit::Y(bitLenInt start, bitLenInt length) Y(start + lcv); } } + /// Apply Pauli Z matrix to each bit void CoherentUnit::Z(bitLenInt start, bitLenInt length) { @@ -898,81 +1018,74 @@ void CoherentUnit::Z(bitLenInt start, bitLenInt length) Z(start + lcv); } } + /// Controlled "phase shift gate" -/** Controlled "phase shift gate" - for each bit, if control bit is true, rotates target bit as e^(-i*\theta/2) around - * |1> state */ void CoherentUnit::CRT(double radians, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRT(radians, control + lcv, target + lcv); } } + /// Controlled dyadic fraction "phase shift gate" -/** Controlled "phase shift gate" - for each bit, if control bit is true, rotates target bit as e^(-i*\theta/2) around - * |1> state */ void CoherentUnit::CRTDyad(int numerator, int denominator, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRTDyad(numerator, denominator, control + lcv, target + lcv); } } + /// Controlled x axis rotation -/** Controlled x axis rotation - for each bit, if control bit is true, rotates as e^(-i*\theta/2) around Pauli x axis */ void CoherentUnit::CRX(double radians, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRX(radians, control + lcv, target + lcv); } } + /// Controlled dyadic fraction x axis rotation gate - for each bit, if control bit is true, rotates target bit as as /// e^(i*(M_PI * numerator) / denominator) around Pauli x axis -/** Controlled dyadic fraction x axis rotation gate - for each bit, if control bit is true, rotates target bit as - * e^(i*(M_PI * numerator) / denominator) around Pauli x axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM - * RADIAN ROTATION OPERATORS. */ void CoherentUnit::CRXDyad(int numerator, int denominator, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRXDyad(numerator, denominator, control + lcv, target + lcv); } } + /// Controlled y axis rotation -/** Controlled y axis rotation - for each bit, if control bit is true, rotates as e^(-i*\theta) around Pauli y axis */ void CoherentUnit::CRY(double radians, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRY(radians, control + lcv, target + lcv); } } + /// Controlled dyadic fraction y axis rotation gate - for each bit, if control bit is true, rotates target bit as /// e^(i*(M_PI * numerator) / denominator) around Pauli y axis -/** Controlled dyadic fraction y axis rotation gate - for each bit, if control bit is true, rotates target bit as - * e^(i*(M_PI * numerator) / denominator) around Pauli y axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM - * RADIAN ROTATION OPERATORS. */ void CoherentUnit::CRYDyad(int numerator, int denominator, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRYDyad(numerator, denominator, control + lcv, target + lcv); } } + /// Controlled z axis rotation -/** Controlled z axis rotation - for each bit, if control bit is true, rotates as e^(-i*\theta) around Pauli z axis */ void CoherentUnit::CRZ(double radians, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRZ(radians, control + lcv, target + lcv); } } + /// Controlled dyadic fraction z axis rotation gate - for each bit, if control bit is true, rotates target bit as /// e^(i*(M_PI * numerator) / denominator) around Pauli z axis -/** Controlled dyadic fraction z axis rotation gate - for each bit, if control bit is true, rotates target bit as - * e^(i*(M_PI * numerator) / denominator) around Pauli z axis. NOTE THAT DYADIC OPERATION ANGLE SIGN IS REVERSED FROM - * RADIAN ROTATION OPERATORS. */ void CoherentUnit::CRZDyad(int numerator, int denominator, bitLenInt control, bitLenInt target, bitLenInt length) { for (bitLenInt lcv = 0; lcv < length; lcv++) { CRZDyad(numerator, denominator, control + lcv, target + lcv); } } + /// Apply controlled Pauli Y matrix to each bit void CoherentUnit::CY(bitLenInt control, bitLenInt target, bitLenInt length) { @@ -980,6 +1093,7 @@ void CoherentUnit::CY(bitLenInt control, bitLenInt target, bitLenInt length) CY(control + lcv, target + lcv); } } + /// Apply controlled Pauli Z matrix to each bit void CoherentUnit::CZ(bitLenInt control, bitLenInt target, bitLenInt length) { @@ -987,7 +1101,8 @@ void CoherentUnit::CZ(bitLenInt control, bitLenInt target, bitLenInt length) CZ(control + lcv, target + lcv); } } -///"AND" compare two bit ranges in CoherentUnit, and store result in range starting at output + +/// "AND" compare two bit ranges in CoherentUnit, and store result in range starting at output void CoherentUnit::AND(bitLenInt inputStart1, bitLenInt inputStart2, bitLenInt outputStart, bitLenInt length) { if (!((inputStart1 == inputStart2) && (inputStart2 == outputStart))) { @@ -996,7 +1111,8 @@ void CoherentUnit::AND(bitLenInt inputStart1, bitLenInt inputStart2, bitLenInt o } } } -///"AND" compare a bit range in CoherentUnit with a classical unsigned integer, and store result in range starting at + +/// "AND" compare a bit range in CoherentUnit with a classical unsigned integer, and store result in range starting at /// output void CoherentUnit::CLAND(bitLenInt qInputStart, bitCapInt classicalInput, bitLenInt outputStart, bitLenInt length) { @@ -1006,7 +1122,8 @@ void CoherentUnit::CLAND(bitLenInt qInputStart, bitCapInt classicalInput, bitLen CLAND(qInputStart + i, cBit, outputStart + i); } } -///"OR" compare two bit ranges in CoherentUnit, and store result in range starting at output + +/// "OR" compare two bit ranges in CoherentUnit, and store result in range starting at output void CoherentUnit::OR(bitLenInt inputStart1, bitLenInt inputStart2, bitLenInt outputStart, bitLenInt length) { if (!((inputStart1 == inputStart2) && (inputStart2 == outputStart))) { @@ -1015,7 +1132,8 @@ void CoherentUnit::OR(bitLenInt inputStart1, bitLenInt inputStart2, bitLenInt ou } } } -///"OR" compare a bit range in CoherentUnit with a classical unsigned integer, and store result in range starting at + +/// "OR" compare a bit range in CoherentUnit with a classical unsigned integer, and store result in range starting at /// output void CoherentUnit::CLOR(bitLenInt qInputStart, bitCapInt classicalInput, bitLenInt outputStart, bitLenInt length) { @@ -1025,7 +1143,8 @@ void CoherentUnit::CLOR(bitLenInt qInputStart, bitCapInt classicalInput, bitLenI CLOR(qInputStart + i, cBit, outputStart + i); } } -///"XOR" compare two bit ranges in CoherentUnit, and store result in range starting at output + +/// "XOR" compare two bit ranges in CoherentUnit, and store result in range starting at output void CoherentUnit::XOR(bitLenInt inputStart1, bitLenInt inputStart2, bitLenInt outputStart, bitLenInt length) { if (!((inputStart1 == inputStart2) && (inputStart2 == outputStart))) { @@ -1034,7 +1153,8 @@ void CoherentUnit::XOR(bitLenInt inputStart1, bitLenInt inputStart2, bitLenInt o } } } -///"XOR" compare a bit range in CoherentUnit with a classical unsigned integer, and store result in range starting at + +/// "XOR" compare a bit range in CoherentUnit with a classical unsigned integer, and store result in range starting at /// output void CoherentUnit::CLXOR(bitLenInt qInputStart, bitCapInt classicalInput, bitLenInt outputStart, bitLenInt length) { @@ -1044,6 +1164,7 @@ void CoherentUnit::CLXOR(bitLenInt qInputStart, bitCapInt classicalInput, bitLen CLXOR(qInputStart + i, cBit, outputStart + i); } } + /// Arithmetic shift left, with last 2 bits as sign and carry void CoherentUnit::ASL(bitLenInt shift, bitLenInt start, bitLenInt length) { @@ -1067,6 +1188,7 @@ void CoherentUnit::ASL(bitLenInt shift, bitLenInt start, bitLenInt length) } } } + /// Arithmetic shift right, with last 2 bits as sign and carry void CoherentUnit::ASR(bitLenInt shift, bitLenInt start, bitLenInt length) { @@ -1090,6 +1212,7 @@ void CoherentUnit::ASR(bitLenInt shift, bitLenInt start, bitLenInt length) } } } + /// Logical shift left, filling the extra bits with |0> void CoherentUnit::LSL(bitLenInt shift, bitLenInt start, bitLenInt length) { @@ -1108,6 +1231,7 @@ void CoherentUnit::LSL(bitLenInt shift, bitLenInt start, bitLenInt length) } } } + /// Logical shift right, filling the extra bits with |0> void CoherentUnit::LSR(bitLenInt shift, bitLenInt start, bitLenInt length) { @@ -1139,6 +1263,7 @@ void CoherentUnit::INC(bitCapInt toAdd, bitLenInt start, bitLenInt length) bitCapInt endPower = 1 << end; bitCapInt iterPower = 1 << (qubitCount - end); bitCapInt maxLCV = iterPower * endPower; + for (i = 0; i < startPower; i++) { for (j = 0; j < maxLCV; j += endPower) { rotate(&(stateVec[0]) + i + j, &(stateVec[0]) + ((lengthPower - toAdd) * startPower) + i + j, @@ -1147,18 +1272,7 @@ void CoherentUnit::INC(bitCapInt toAdd, bitLenInt start, bitLenInt length) } } } -/// Add integer (without sign) -// void CoherentUnit::INC(bitCapInt toAdd, bitLenInt start, bitLenInt length) { -// par_for_reg(start, length, qubitCount, toAdd, &(stateVec[0]), -// [](const bitCapInt k, const int cpu, const bitCapInt startPower, const bitCapInt endPower, -// const bitCapInt lengthPower, const bitCapInt toAdd, Complex16* stateArray) { -// rotate(stateArray + k, -// stateArray + ((lengthPower - toAdd) * startPower) + k, -// stateArray + endPower + k, -// startPower); -// } -// ); -//} + /// Add BCD integer (without sign) void CoherentUnit::INCBCD(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length) { @@ -1215,6 +1329,7 @@ void CoherentUnit::INCBCD(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt lengt }); ResetStateVec(nStateVec); } + /// Add BCD integer (without sign, with carry) void CoherentUnit::INCBCDC( const bitCapInt toAdd, const bitLenInt inOutStart, const bitLenInt length, const bitLenInt carryIndex) @@ -1351,6 +1466,7 @@ void CoherentUnit::INCBCDC( } ResetStateVec(nStateVec); } + /// Add integer (without sign, with carry) void CoherentUnit::INCC( const bitCapInt toAdd, const bitLenInt inOutStart, const bitLenInt length, const bitLenInt carryIndex) @@ -1407,10 +1523,14 @@ void CoherentUnit::INCC( } ResetStateVec(nStateVec); } -/// Add integer (with sign, without carry) -/** Add an integer to the register, with sign and without carry. Because the register length is an arbitrary number of - * bits, the sign bit position on the integer to add is variable. Hence, the integer to add is specified as cast to an - * unsigned format, with the sign bit assumed to be set at the appropriate position before the cast. */ + +/** + * Add an integer to the register, with sign and without carry. Because the + * register length is an arbitrary number of bits, the sign bit position on the + * integer to add is variable. Hence, the integer to add is specified as cast + * to an unsigned format, with the sign bit assumed to be set at the + * appropriate position before the cast. + */ void CoherentUnit::INCS(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, bitLenInt overflowIndex) { bitCapInt inOutMask = 0; @@ -1459,10 +1579,14 @@ void CoherentUnit::INCS(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, } ResetStateVec(nStateVec); } -/// Add integer (with sign, with carry) -/** Add an integer to the register, with sign and with carry. Because the register length is an arbitrary number of - * bits, the sign bit position on the integer to add is variable. Hence, the integer to add is specified as cast to an - * unsigned format, with the sign bit assumed to be set at the appropriate position before the cast. */ + +/** + * Add an integer to the register, with sign and with carry. Because the + * register length is an arbitrary number of bits, the sign bit position on the + * integer to add is variable. Hence, the integer to add is specified as cast + * to an unsigned format, with the sign bit assumed to be set at the + * appropriate position before the cast. + */ void CoherentUnit::INCSC( bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex) { @@ -1547,6 +1671,7 @@ void CoherentUnit::INCSC( } ResetStateVec(nStateVec); } + /// Subtract integer (without sign) void CoherentUnit::DEC(bitCapInt toSub, bitLenInt start, bitLenInt length) { @@ -1567,18 +1692,7 @@ void CoherentUnit::DEC(bitCapInt toSub, bitLenInt start, bitLenInt length) } } } -/// Subtract integer (without sign) -// void CoherentUnit::DEC(bitCapInt toSub, bitLenInt start, bitLenInt length) { -// par_for_reg(start, length, qubitCount, toSub, &(stateVec[0]), -// [](const bitCapInt k, const int cpu, const bitCapInt startPower, const bitCapInt endPower, -// const bitCapInt lengthPower, const bitCapInt toSub, Complex16* stateArray) { -// rotate(stateArray + k, -// stateArray + (toSub * startPower) + k, -// stateArray + endPower + k, -// startPower); -// } -// ); -//} + /// Subtract BCD integer (without sign) void CoherentUnit::DECBCD(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length) { @@ -1635,6 +1749,7 @@ void CoherentUnit::DECBCD(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt lengt }); ResetStateVec(nStateVec); } + /// Subtract integer (without sign, with carry) void CoherentUnit::DECC( const bitCapInt toSub, const bitLenInt inOutStart, const bitLenInt length, const bitLenInt carryIndex) @@ -1691,10 +1806,12 @@ void CoherentUnit::DECC( } ResetStateVec(nStateVec); } -/// Subtract integer (with sign, without carry) -/** Subtract an integer from the register, with sign and without carry. Because the register length is an arbitrary + +/** + * Subtract an integer from the register, with sign and without carry. Because the register length is an arbitrary * number of bits, the sign bit position on the integer to add is variable. Hence, the integer to add is specified as - * cast to an unsigned format, with the sign bit assumed to be set at the appropriate position before the cast. */ + * cast to an unsigned format, with the sign bit assumed to be set at the appropriate position before the cast. + */ void CoherentUnit::DECS(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, bitLenInt overflowIndex) { bitCapInt inOutMask = 0; @@ -1743,10 +1860,14 @@ void CoherentUnit::DECS(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, } ResetStateVec(nStateVec); } -/// Subtract integer (with sign, with carry) -/** Subtract an integer from the register, with sign and with carry. Because the register length is an arbitrary number - * of bits, the sign bit position on the integer to add is variable. Hence, the integer to add is specified as cast to - * an unsigned format, with the sign bit assumed to be set at the appropriate position before the cast. */ + +/** + * Subtract an integer from the register, with sign and with carry. Because the + * register length is an arbitrary number of bits, the sign bit position on the + * integer to add is variable. Hence, the integer to add is specified as cast + * to an unsigned format, with the sign bit assumed to be set at the + * appropriate position before the cast. + */ void CoherentUnit::DECSC( bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex) { @@ -1831,6 +1952,7 @@ void CoherentUnit::DECSC( } ResetStateVec(nStateVec); } + /// Subtract BCD integer (without sign, with carry) void CoherentUnit::DECBCDC( const bitCapInt toSub, const bitLenInt inOutStart, const bitLenInt length, const bitLenInt carryIndex) @@ -1968,9 +2090,10 @@ void CoherentUnit::DECBCDC( ResetStateVec(nStateVec); } -/// Add two binary-coded decimal numbers. -/** Add BCD number of "length" bits in "inStart" to BCD number of "length" bits in "inOutStart," and store result in - * "inOutStart." */ +/** + * Add BCD number of "length" bits in "inStart" to BCD number of "length" bits in "inOutStart," and store result in + * "inOutStart." + */ void CoherentUnit::ADDBCD(const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length) { bitCapInt nibbleCount = length / 4; @@ -2031,9 +2154,12 @@ void CoherentUnit::ADDBCD(const bitLenInt inOutStart, const bitLenInt inStart, c }); ResetStateVec(nStateVec); } -/// Add two quantum integers with carry bit -/** Add integer of "length" bits in "inStart" to integer of "length" bits in "inOutStart," and store result in - * "inOutStart." Get carry value from bit at "carryIndex" and place end result into this bit. */ + +/** + * Add integer of "length" bits in "inStart" to integer of "length" bits in + * "inOutStart," and store result in "inOutStart." Get carry value from bit at + * "carryIndex" and place end result into this bit. + */ void CoherentUnit::ADDC( const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length, const bitLenInt carryIndex) { @@ -2051,8 +2177,8 @@ void CoherentUnit::ADDC( bitCapInt edgeMask = inOutMask | carryMask | otherMask; std::unique_ptr nStateVec(new Complex16[maxQPower]); std::fill(&(nStateVec[0]), &(nStateVec[0]) + maxQPower, Complex16(0.0, 0.0)); - bitCapInt bciArgs[9] - = { inOutMask, inMask, carryMask, otherMask, lengthPower, inOutStart, inStart, carryIndex, edgeMask }; + bitCapInt bciArgs[9] = { inOutMask, inMask, carryMask, otherMask, lengthPower, inOutStart, inStart, carryIndex, + edgeMask }; par_for_skip(0, maxQPower >> 1, 1 << carryIndex, &(stateVec[0]), bciArgs, &(nStateVec[0]), [](const bitCapInt lcv, const int cpu, const Complex16* stateVec, const bitCapInt* bciArgs, Complex16* nStateVec) { @@ -2102,9 +2228,12 @@ void CoherentUnit::ADDC( } ResetStateVec(nStateVec); } -/// Add two signed quantum integers with overflow bit -/** Add signed integer of "length" bits in "inStart" to signed integer of "length" bits in "inOutStart," and store - * result in "inOutStart." Set overflow bit when input to output wraps past minimum or maximum integer. */ + +/** + * Add signed integer of "length" bits in "inStart" to signed integer of + * "length" bits in "inOutStart," and store result in "inOutStart." Set + * overflow bit when input to output wraps past minimum or maximum integer. + */ void CoherentUnit::ADDS( const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length, const bitLenInt overflowIndex) { @@ -2161,10 +2290,13 @@ void CoherentUnit::ADDS( } ResetStateVec(nStateVec); } -/// Add two quantum integers with carry bit and overflow bit -/** Add integer of "length" bits in "inStart" to integer of "length" bits in "inOutStart," and store result in - * "inOutStart." Get carry value from bit at "carryIndex" and place end result into this bit. Set overflow for signed - * addition if result wraps past the minimum or maximum signed integer. */ + +/** + * Add integer of "length" bits in "inStart" to integer of "length" bits in + * "inOutStart," and store result in "inOutStart." Get carry value from bit at + * "carryIndex" and place end result into this bit. Set overflow for signed + * addition if result wraps past the minimum or maximum signed integer. + */ void CoherentUnit::ADDSC(const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length, const bitLenInt overflowIndex, const bitLenInt carryIndex) { @@ -2259,9 +2391,11 @@ void CoherentUnit::ADDSC(const bitLenInt inOutStart, const bitLenInt inStart, co } ResetStateVec(nStateVec); } -/// Add two binary-coded decimal numbers. -/** Add BCD number of "length" bits in "inStart" to BCD number of "length" bits in "inOutStart," and store result in - * "inOutStart." */ + +/** + * Add BCD number of "length" bits in "inStart" to BCD number of "length" bits + * in "inOutStart," and store result in "inOutStart." + */ void CoherentUnit::ADDBCDC( const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length, const bitLenInt carryIndex) { @@ -2402,9 +2536,10 @@ void CoherentUnit::ADDBCDC( ResetStateVec(nStateVec); } -/// Subtract two binary-coded decimal numbers. -/** Subtract BCD number of "length" bits in "inStart" from BCD number of "length" bits in "inOutStart," and store result - * in "inOutStart." */ +/** + * Subtract BCD number of "length" bits in "inStart" from BCD number of "length" bits in "inOutStart," and store result + * in "inOutStart." + */ void CoherentUnit::SUBBCD(const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length) { bitCapInt nibbleCount = length / 4; @@ -2465,9 +2600,12 @@ void CoherentUnit::SUBBCD(const bitLenInt inOutStart, const bitLenInt inStart, c }); ResetStateVec(nStateVec); } -/// Subtract two quantum integers with carry bit -/** Subtract integer of "length" - 1 bits in "toSub" from integer of "length" - 1 bits in "inOutStart," and store result - * in "inOutStart." Get carry value from bit at "carryIndex" and place end result into this bit. */ + +/** + * Subtract integer of "length" - 1 bits in "toSub" from integer of "length" - + * 1 bits in "inOutStart," and store result in "inOutStart." Get carry value + * from bit at "carryIndex" and place end result into this bit. + */ void CoherentUnit::SUBC( const bitLenInt inOutStart, const bitLenInt toSub, const bitLenInt length, const bitLenInt carryIndex) { @@ -2485,8 +2623,8 @@ void CoherentUnit::SUBC( otherMask ^= inOutMask | inMask | carryMask; std::unique_ptr nStateVec(new Complex16[maxQPower]); std::fill(&(nStateVec[0]), &(nStateVec[0]) + maxQPower, Complex16(0.0, 0.0)); - bitCapInt bciArgs[9] - = { inOutMask, inMask, carryMask, otherMask, lengthPower, inOutStart, toSub, carryIndex, edgeMask }; + bitCapInt bciArgs[9] = { inOutMask, inMask, carryMask, otherMask, lengthPower, inOutStart, toSub, carryIndex, + edgeMask }; par_for_skip(0, maxQPower >> 1, 1 << carryIndex, &(stateVec[0]), bciArgs, &(nStateVec[0]), [](const bitCapInt lcv, const int cpu, const Complex16* stateVec, const bitCapInt* bciArgs, Complex16* nStateVec) { @@ -2534,9 +2672,11 @@ void CoherentUnit::SUBC( } ResetStateVec(nStateVec); } -/// Subtract two signed quantum integers with overflow bit -/** Subtract signed integer of "length" bits in "inStart" from signed integer of "length" bits in "inOutStart," and - * store result in "inOutStart." Set overflow bit when input to output wraps past minimum or maximum integer. */ + +/** + * Subtract signed integer of "length" bits in "inStart" from signed integer of "length" bits in "inOutStart," and + * $store result in "inOutStart." Set overflow bit when input to output wraps past minimum or maximum integer. + */ void CoherentUnit::SUBS( const bitLenInt inOutStart, const bitLenInt toSub, const bitLenInt length, const bitLenInt overflowIndex) { @@ -2593,10 +2733,13 @@ void CoherentUnit::SUBS( } ResetStateVec(nStateVec); } -/// Subtract two quantum integers with carry bit and overflow bit -/** Subtract integer of "length" bits in "inStart" from integer of "length" bits in "inOutStart," and store result in - * "inOutStart." Get carry value from bit at "carryIndex" and place end result into this bit. Set overflow for signed - * addition if result wraps past the minimum or maximum signed integer. */ + +/** + * Subtract integer of "length" bits in "inStart" from integer of "length" bits + * in "inOutStart," and store result in "inOutStart." Get carry value from bit + * at "carryIndex" and place end result into this bit. Set overflow for signed + * addition if result wraps past the minimum or maximum signed integer. + */ void CoherentUnit::SUBSC(const bitLenInt inOutStart, const bitLenInt toSub, const bitLenInt length, const bitLenInt overflowIndex, const bitLenInt carryIndex) { @@ -2689,9 +2832,11 @@ void CoherentUnit::SUBSC(const bitLenInt inOutStart, const bitLenInt toSub, cons } ResetStateVec(nStateVec); } -/// Add two binary-coded decimal numbers. -/** Add BCD number of "length" bits in "inStart" to BCD number of "length" bits in "inOutStart," and store result in - * "inOutStart." */ + +/** + * Add BCD number of "length" bits in "inStart" to BCD number of "length" bits + * in "inOutStart," and store result in "inOutStart." + */ void CoherentUnit::SUBBCDC( const bitLenInt inOutStart, const bitLenInt inStart, const bitLenInt length, const bitLenInt carryIndex) { @@ -2717,8 +2862,8 @@ void CoherentUnit::SUBBCDC( bitCapInt edgeMask = maxMask | inMask; std::unique_ptr nStateVec(new Complex16[maxQPower]); std::fill(&(nStateVec[0]), &(nStateVec[0]) + maxQPower, Complex16(0.0, 0.0)); - bitCapInt bciArgs[9] - = { inOutMask, inMask, carryMask, otherMask, inOutStart, inStart, nibbleCount, edgeMask, maxMask }; + bitCapInt bciArgs[9] = { inOutMask, inMask, carryMask, otherMask, inOutStart, inStart, nibbleCount, edgeMask, + maxMask }; par_for_skip(0, maxQPower >> 1, 1 << carryIndex, &(stateVec[0]), bciArgs, &(nStateVec[0]), [](const bitCapInt lcv, const int cpu, const Complex16* stateVec, const bitCapInt* bciArgs, Complex16* nStateVec) { @@ -2832,6 +2977,7 @@ void CoherentUnit::SUBBCDC( } ResetStateVec(nStateVec); } + /// Quantum Fourier Transform - Apply the quantum Fourier transform to the register void CoherentUnit::QFT(bitLenInt start, bitLenInt length) { @@ -3008,6 +3154,7 @@ void CoherentUnit::ApplyControlled2x2(bitLenInt control, bitLenInt target, const } Apply2x2(qPowers[0], qPowers[1], mtrx, 2, qPowersSorted, false, doCalcNorm); } + void CoherentUnit::ApplyAntiControlled2x2(bitLenInt control, bitLenInt target, const Complex16* mtrx, bool doCalcNorm) { bitCapInt qPowers[3]; @@ -3033,6 +3180,7 @@ void CoherentUnit::NormalizeState() } runningNorm = 1.0; } + void CoherentUnit::Reverse(bitLenInt first, bitLenInt last) { while ((first < last) && (first < (last - 1))) { @@ -3041,5 +3189,6 @@ void CoherentUnit::Reverse(bitLenInt first, bitLenInt last) first++; } } + void CoherentUnit::UpdateRunningNorm() { runningNorm = par_norm(maxQPower, &(stateVec[0])); } } // namespace Qrack diff --git a/qregister_opencl.cpp b/qregister_opencl.cpp index 3e2245c7c..c09c8ec5f 100644 --- a/qregister_opencl.cpp +++ b/qregister_opencl.cpp @@ -49,8 +49,8 @@ void CoherentUnitOCL::InitOCL() cl::Context context = *(clObj->GetContextPtr()); // create buffers on device (allocate space on GPU) - stateBuffer - = cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(stateVec[0])); + stateBuffer = + cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(stateVec[0])); cmplxBuffer = cl::Buffer(context, CL_MEM_READ_ONLY, sizeof(Complex16) * 5); ulongBuffer = cl::Buffer(context, CL_MEM_READ_ONLY, sizeof(bitCapInt) * 10); nrmBuffer = cl::Buffer(context, CL_MEM_READ_WRITE, sizeof(double) * CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE); @@ -67,8 +67,8 @@ void CoherentUnitOCL::ReInitOCL() cl::Context context = *(clObj->GetContextPtr()); // create buffers on device (allocate space on GPU) - stateBuffer - = cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(stateVec[0])); + stateBuffer = + cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(stateVec[0])); queue.enqueueMapBuffer(stateBuffer, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Complex16) * maxQPower); } @@ -131,8 +131,8 @@ void CoherentUnitOCL::ROL(bitLenInt shift, bitLenInt start, bitLenInt length) queue.enqueueWriteBuffer(ulongBuffer, CL_FALSE, 0, sizeof(bitCapInt) * 10, bciArgs); std::unique_ptr nStateVec(new Complex16[maxQPower]); cl::Context context = *(clObj->GetContextPtr()); - cl::Buffer nStateBuffer - = cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); + cl::Buffer nStateBuffer = + cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); cl::Kernel rol = *(clObj->GetROLPtr()); rol.setArg(0, stateBuffer); rol.setArg(1, ulongBuffer); @@ -164,8 +164,8 @@ void CoherentUnitOCL::ROR(bitLenInt shift, bitLenInt start, bitLenInt length) queue.enqueueWriteBuffer(ulongBuffer, CL_FALSE, 0, sizeof(bitCapInt) * 10, bciArgs); std::unique_ptr nStateVec(new Complex16[maxQPower]); cl::Context context = *(clObj->GetContextPtr()); - cl::Buffer nStateBuffer - = cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); + cl::Buffer nStateBuffer = + cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); cl::Kernel ror = *(clObj->GetRORPtr()); ror.setArg(0, stateBuffer); ror.setArg(1, ulongBuffer); @@ -201,8 +201,8 @@ void CoherentUnitOCL::ADD(const bitLenInt inOutStart, const bitLenInt inStart, c queue.enqueueWriteBuffer(ulongBuffer, CL_FALSE, 0, sizeof(bitCapInt) * 10, bciArgs); std::unique_ptr nStateVec(new Complex16[maxQPower]); cl::Context context = *(clObj->GetContextPtr()); - cl::Buffer nStateBuffer - = cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); + cl::Buffer nStateBuffer = + cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); cl::Kernel add = *(clObj->GetADDPtr()); add.setArg(0, stateBuffer); add.setArg(1, ulongBuffer); @@ -238,8 +238,8 @@ void CoherentUnitOCL::SUB(const bitLenInt inOutStart, const bitLenInt toSub, con queue.enqueueWriteBuffer(ulongBuffer, CL_FALSE, 0, sizeof(bitCapInt) * 10, bciArgs); std::unique_ptr nStateVec(new Complex16[maxQPower]); cl::Context context = *(clObj->GetContextPtr()); - cl::Buffer nStateBuffer - = cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); + cl::Buffer nStateBuffer = + cl::Buffer(context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, sizeof(Complex16) * maxQPower, &(nStateVec[0])); cl::Kernel sub = *(clObj->GetSUBPtr()); sub.setArg(0, stateBuffer); sub.setArg(1, ulongBuffer); diff --git a/qregister_opencl.hpp b/qregister_opencl.hpp index 2f4b696a3..ba2ae2718 100644 --- a/qregister_opencl.hpp +++ b/qregister_opencl.hpp @@ -56,4 +56,4 @@ class CoherentUnitOCL : public CoherentUnit { virtual void Apply2x2(bitCapInt offset1, bitCapInt offset2, const Complex16* mtrx, const bitLenInt bitCount, const bitCapInt* qPowersSorted, bool doApplyNorm, bool doCalcNorm); }; -} +} // namespace Qrack diff --git a/qregister_software.cpp b/qregister_software.cpp index cb8efdea5..5748a18f0 100644 --- a/qregister_software.cpp +++ b/qregister_software.cpp @@ -133,8 +133,8 @@ void CoherentUnit::SUB(const bitLenInt inOutStart, const bitLenInt toSub, const bitCapInt inOutInt = inOutRes >> (bciArgs[4]); bitCapInt inRes = (lcv & (bciArgs[1])); bitCapInt inInt = inRes >> (bciArgs[5]); - nStateVec[(((inOutInt - inInt + (bciArgs[3])) & bciArgs[3]) << (bciArgs[4])) + otherRes + inRes] - = stateVec[lcv]; + nStateVec[(((inOutInt - inInt + (bciArgs[3])) & bciArgs[3]) << (bciArgs[4])) + otherRes + inRes] = + stateVec[lcv]; } }); stateVec.reset();