Commit 33fc48fb authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

add integer multiply



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent cb585a05
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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
+24 −0
Original line number Diff line number Diff line
@@ -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

@@ -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); }
}