Loading examples/arithmetic/integer_add.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,20 @@ __qpu__ void test_add_integer_mod(qreg q, qubit anc) { Measure(anc); } __qpu__ void test_mul_integer(qreg x, qreg b, qubit anc, int a, int N) { // b = 1; X(b[0]); // x = |1> + |3> X(x[0]); H(x[1]); // ==> |a*x + b> mul_integer_mod(x, b, anc, a, N); Measure(b); Measure(x); } int main(int argc, char **argv) { set_shots(1024); auto a = qalloc(3); Loading @@ -38,5 +52,25 @@ int main(int argc, char **argv) { anc.print(); // anc returns to 0 qcor_expect(anc.counts()["0"] == 1024); // Test modular multiply int a_val = 3; // Large modulo => exact answer int N_val = 16; // More qubits to save the result auto b_reg = qalloc(5); auto x_reg = qalloc(2); auto anc_reg = qalloc(1); test_mul_integer::print_kernel(x_reg, b_reg, anc_reg[0], a_val, N_val); test_mul_integer(x_reg, b_reg, anc_reg[0], a_val, N_val); // x = |1> + |3>; |b> = 1 // |a*x + b> = |4> + |10> b_reg.print(); qcor_expect(b_reg.counts().size() == 2); // 4 qcor_expect(b_reg.counts()["00100"] > 400); // 10 = 8 + 2 qcor_expect(b_reg.counts()["01010"] > 400); x_reg.print(); return 0; } No newline at end of file lib/impl/integer_arithmetic.hpp +24 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ void genAngles(std::vector<double> &io_angles, int a, int nbQubits) { angle *= M_PI; } } inline void calcPowMultMod(int &result, int i, int a, int N) { result = (1 << i) * a % N; } } // namespace internal } // namespace qcor Loading Loading @@ -114,3 +118,23 @@ __qpu__ void add_integer_mod(qreg q, qubit anc, int a, int N) { compute { qft_opt_swap(q, 0); } action { phase_add_integer_mod(q, anc, a, N); } } // Modular multiply in phase basis: // See Fig. 6 of https://arxiv.org/pdf/quant-ph/0205095.pdf // |x>|b> ==> |x> |b + ax mod N> // i.e. if b == 0 ==> the result |ax mod N> is stored in b __qpu__ void phase_mul_integer_mod(qreg x, qreg b, qubit anc, int a, int N) { for (int i = 0; i < x.size(); ++i) { // add operand = 2^i * a int operand; qcor::internal::calcPowMultMod(operand, i, a, N); phase_add_integer_mod::ctrl(x[i], b, anc, operand, N); } } __qpu__ void mul_integer_mod(qreg x, qreg b, qubit anc, int a, int N) { // Bring it to Fourier basis // (IQFT automatically) compute { qft_opt_swap(b, 0); } action { phase_mul_integer_mod(x, b, anc, a, N); } } Loading
examples/arithmetic/integer_add.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,20 @@ __qpu__ void test_add_integer_mod(qreg q, qubit anc) { Measure(anc); } __qpu__ void test_mul_integer(qreg x, qreg b, qubit anc, int a, int N) { // b = 1; X(b[0]); // x = |1> + |3> X(x[0]); H(x[1]); // ==> |a*x + b> mul_integer_mod(x, b, anc, a, N); Measure(b); Measure(x); } int main(int argc, char **argv) { set_shots(1024); auto a = qalloc(3); Loading @@ -38,5 +52,25 @@ int main(int argc, char **argv) { anc.print(); // anc returns to 0 qcor_expect(anc.counts()["0"] == 1024); // Test modular multiply int a_val = 3; // Large modulo => exact answer int N_val = 16; // More qubits to save the result auto b_reg = qalloc(5); auto x_reg = qalloc(2); auto anc_reg = qalloc(1); test_mul_integer::print_kernel(x_reg, b_reg, anc_reg[0], a_val, N_val); test_mul_integer(x_reg, b_reg, anc_reg[0], a_val, N_val); // x = |1> + |3>; |b> = 1 // |a*x + b> = |4> + |10> b_reg.print(); qcor_expect(b_reg.counts().size() == 2); // 4 qcor_expect(b_reg.counts()["00100"] > 400); // 10 = 8 + 2 qcor_expect(b_reg.counts()["01010"] > 400); x_reg.print(); return 0; } No newline at end of file
lib/impl/integer_arithmetic.hpp +24 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ void genAngles(std::vector<double> &io_angles, int a, int nbQubits) { angle *= M_PI; } } inline void calcPowMultMod(int &result, int i, int a, int N) { result = (1 << i) * a % N; } } // namespace internal } // namespace qcor Loading Loading @@ -114,3 +118,23 @@ __qpu__ void add_integer_mod(qreg q, qubit anc, int a, int N) { compute { qft_opt_swap(q, 0); } action { phase_add_integer_mod(q, anc, a, N); } } // Modular multiply in phase basis: // See Fig. 6 of https://arxiv.org/pdf/quant-ph/0205095.pdf // |x>|b> ==> |x> |b + ax mod N> // i.e. if b == 0 ==> the result |ax mod N> is stored in b __qpu__ void phase_mul_integer_mod(qreg x, qreg b, qubit anc, int a, int N) { for (int i = 0; i < x.size(); ++i) { // add operand = 2^i * a int operand; qcor::internal::calcPowMultMod(operand, i, a, N); phase_add_integer_mod::ctrl(x[i], b, anc, operand, N); } } __qpu__ void mul_integer_mod(qreg x, qreg b, qubit anc, int a, int N) { // Bring it to Fourier basis // (IQFT automatically) compute { qft_opt_swap(b, 0); } action { phase_mul_integer_mod(x, b, anc, a, N); } }