7 void genAngles(std::vector<double> &io_angles,
int a,
int nbQubits) {
9 io_angles.resize(nbQubits);
10 std::fill(io_angles.begin(), io_angles.end(), 0.0);
12 for (
int i = 0; i < nbQubits; ++i) {
13 int bitIdx = nbQubits - i - 1;
14 auto &angle = io_angles[bitIdx];
15 for (
int j = i; j < nbQubits; ++j) {
17 int bitShift = nbQubits - j - 1;
18 if (((1 << bitShift) & a) != 0) {
19 angle += std::pow(2.0, -(j - i));
26 inline void calcPowMultMod(
int &result,
int i,
int a,
int N) {
27 result = (1 << i) * a % N;
31 inline std::tuple<int, int, int> egcd(
int a,
int b) {
33 int m1 = 0, m2 = 1, n1 = 1, n2 = 0;
36 q = a / b, r = a - q * b;
37 m = m2 - q * m1, n = n2 - q * n1;
39 m2 = m1, m1 = m, n2 = n1, n1 = n;
42 c = a, m = m2, n = n2;
51 return std::make_tuple(m, n, c);
55 inline void modinv(
int &result,
int a,
int p) {
58 std::tie(x, y, gcd_ap) = egcd(p, a);
59 result = (y > 0) ? y : y + p;
65 __qpu__
void majority(qubit a, qubit b, qubit c) {
73 __qpu__
void unmajority(qubit a, qubit b, qubit c) {
81 __qpu__
void ripple_add(qreg a, qreg b, qubit c_in, qubit c_out) {
82 majority(c_in, b[0], a[0]);
83 for (
auto j : range(a.size() - 1)) {
84 majority(a[j], b[j + 1], a[j + 1]);
87 X::ctrl(a.tail(), c_out);
89 for (
int j = a.size() - 2; j >= 0; --j) {
90 unmajority(a[j], b[j + 1], a[j + 1]);
92 unmajority(c_in, b[0], a[0]);
96 __qpu__
void integer_init(qreg a,
int val) {
98 for (
auto i : range(a.size())) {
106 __qpu__
void phase_add_integer(qreg q,
int a) {
107 std::vector<double> angles;
108 qcor::internal::genAngles(angles, a, q.size());
109 for (
int i = 0; i < q.size(); ++i) {
116 __qpu__
void add_integer(qreg q,
int a) {
119 compute { qft_opt_swap(q, 0); }
120 action { phase_add_integer(q, a); }
127 __qpu__
void phase_add_integer_mod(qreg q, qubit anc,
int a,
int N) {
129 phase_add_integer(q, a);
130 phase_add_integer::adjoint(q, N);
131 qft_opt_swap::adjoint(q, 0);
132 X::ctrl(q.tail(), anc);
134 phase_add_integer::ctrl(anc, q, N);
135 phase_add_integer::adjoint(q, a);
136 qft_opt_swap::adjoint(q, 0);
138 X::ctrl(q.tail(), anc);
141 phase_add_integer(q, a);
147 __qpu__
void add_integer_mod_impl(qreg q, qubit anc,
int a,
int N) {
150 compute { qft_opt_swap(q, 0); }
151 action { phase_add_integer_mod(q, anc, a, N); }
154 __qpu__
void add_integer_mod(qreg q,
int a,
int N) {
155 auto anc = qalloc(1);
156 add_integer_mod_impl(q, anc[0], a, N);
163 __qpu__
void phase_mul_integer_mod(qreg x, qreg b, qubit anc,
int a,
int N) {
164 for (
int i = 0; i < x.size(); ++i) {
167 qcor::internal::calcPowMultMod(operand, i, a, N);
168 phase_add_integer_mod::ctrl(x[i], b, anc, operand, N);
172 __qpu__
void mul_integer_mod_impl(qreg x, qreg b, qubit anc,
int a,
int N) {
175 compute { qft_opt_swap(b, 0); }
176 action { phase_mul_integer_mod(x, b, anc, a, N); }
179 __qpu__
void mul_integer_mod(qreg x, qreg b,
int a,
int N) {
180 auto anc = qalloc(1);
181 mul_integer_mod_impl(x, b, anc[0], a, N);
188 __qpu__
void mul_integer_mod_in_place_impl(qreg x, qreg aux_reg, qubit anc,
int a,
int N) {
190 mul_integer_mod_impl(x, aux_reg, anc, a, N);
192 for (
int i = 0; i < x.size(); ++i) {
193 Swap(x[i], aux_reg[i]);
197 qcor::internal::modinv(aInv, a, N);
199 mul_integer_mod_impl::adjoint(x, aux_reg, anc, aInv, N);
203 __qpu__
void mul_integer_mod_in_place(qreg x,
int a,
int N) {
204 auto anc_reg = qalloc(1);
205 mul_integer_mod_in_place_impl(x, qalloc(x.size() + 1), anc_reg[0], a, N);