namespace Kadet.Quantum.Util { open Microsoft.Quantum.Canon; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Convert; operation HalfAdd(a: Qubit, b: Qubit, carry: Qubit, sum: Qubit): Unit { CNOT(a, sum); // entangle sum with a, so sum behaves in same way CNOT(b, sum); // xor sum (entagled with a) with b CCNOT(a, b, carry); // carry is set only if a and b } operation FullAdd(a: Qubit, b: Qubit, carry: Qubit, sum: Qubit): Unit { CCNOT(a, b, sum); CNOT(a, b); CCNOT(b, carry, sum); CNOT(b, carry); CNOT(a, b); SWAP(sum, carry); } operation Add(a: Qubit[], b: Qubit[], sum: Qubit[]): Unit { let max = Length(a) - 1; let carry = sum[max + 1]; for (i in 0..max) { FullAdd(a[i], b[i], carry, sum[i]); } } operation ApplyToMask<'T>(mask: Int, action: ('T => Unit is Ctl+Adj), target: 'T[]): Unit is Ctl+Adj { let count = Length(target); let bits = IntAsBoolArray(((1 <<< count) - 1) &&& mask, count); for (i in 0..count - 1) { ApplyIfCA(action, bits[i], target[i]); } } operation ApplyIfEquals<'T>(input: Qubit[], value: Int, Action: ('T => Unit is Ctl+Adj), target: 'T): Unit is Adj { let mask = ~~~value; ApplyToMask(mask, X, input); Controlled Action(input, target); ApplyToMask(mask, X, input); } operation ApplyMultipleTimes<'T>(times: Int, op: ('T => Unit), target: 'T): Unit { for (i in 0..times - 1) { op(target); } } operation InitFromInt(reg: Qubit[], number: Int): Unit is Ctl+Adj { let max = Length(reg) - 1; ApplyToMask(number, X, reg); } }