diff --git a/src/framework/operations.hpp b/src/framework/operations.hpp index dc4cbb5b06..2f6a79adf6 100644 --- a/src/framework/operations.hpp +++ b/src/framework/operations.hpp @@ -270,9 +270,6 @@ class BinaryExpr : public CExpr { case BinaryOp::BitAnd: case BinaryOp::BitOr: case BinaryOp::BitXor: - if (left->type->type != ValueType::Uint) - throw std::invalid_argument( - R"(bit operation allows only for uint expressions.)"); break; case BinaryOp::LogicAnd: case BinaryOp::LogicOr: @@ -299,10 +296,20 @@ class BinaryExpr : public CExpr { virtual bool eval_bool(const std::string &memory) { switch (op) { case BinaryOp::BitAnd: + if (left->type->type == ValueType::Uint) + return eval_uint(memory) != 0; + else + return left->eval_bool(memory) && right->eval_bool(memory); case BinaryOp::BitOr: + if (left->type->type == ValueType::Uint) + return eval_uint(memory) != 0; + else + return left->eval_bool(memory) || right->eval_bool(memory); case BinaryOp::BitXor: - throw std::invalid_argument( - R"(eval_bool is called for Bit* binary expression.)"); + if (left->type->type == ValueType::Uint) + return eval_uint(memory) != 0; + else + return left->eval_bool(memory) ^ right->eval_bool(memory); case BinaryOp::LogicAnd: return left->eval_bool(memory) && right->eval_bool(memory); case BinaryOp::LogicOr: diff --git a/test/terra/backends/aer_simulator/test_control_flow.py b/test/terra/backends/aer_simulator/test_control_flow.py index a9ef52c198..89a8b07713 100644 --- a/test/terra/backends/aer_simulator/test_control_flow.py +++ b/test/terra/backends/aer_simulator/test_control_flow.py @@ -1100,3 +1100,90 @@ def test_while_expr_loop_break(self, method): counts = result.get_counts() self.assertEqual(len(counts), 1) self.assertIn("1 1", counts) + + @data("statevector", "density_matrix", "matrix_product_state", "stabilizer") + def test_bit_and_operation(self, method): + """test bit-and operation""" + qr = QuantumRegister(7) + cr = ClassicalRegister(7) + qc = QuantumCircuit(qr, cr) + qc.x(0) + qc.x(2) + qc.measure(range(4), range(4)) # 0101 + qc.barrier() + b01 = expr.bit_and(cr[0], cr[1]) # 1 & 0 -> 0 + with qc.if_test(b01): + qc.x(4) # q4 -> 0 + + b02 = expr.bit_and(cr[0], cr[2]) # 1 & 1 -> 1 + with qc.if_test(b02): + qc.x(5) # q5 -> 0 + + b13 = expr.bit_and(cr[1], cr[3]) # 0 & 0 -> 0 + with qc.if_test(b13): + qc.x(6) # q6 -> 0 + + qc.measure(range(7), range(7)) # 0100101 + + backend = self.backend(method=method) + counts = backend.run(qc).result().get_counts() + self.assertEqual(len(counts), 1) + self.assertIn("0100101", counts) + + @data("statevector", "density_matrix", "matrix_product_state", "stabilizer") + def test_bit_or_operation(self, method): + """test bit-or operation""" + qr = QuantumRegister(7) + cr = ClassicalRegister(7) + qc = QuantumCircuit(qr, cr) + qc.x(0) + qc.x(2) + qc.measure(range(4), range(4)) # 0101 + qc.barrier() + b01 = expr.bit_or(cr[0], cr[1]) # 1 & 0 -> 1 + with qc.if_test(b01): + qc.x(4) # q4 -> 1 + + b02 = expr.bit_or(cr[0], cr[2]) # 1 & 1 -> 1 + with qc.if_test(b02): + qc.x(5) # q5 -> 0 + + b13 = expr.bit_or(cr[1], cr[3]) # 0 & 0 -> 0 + with qc.if_test(b13): + qc.x(6) # q6 -> 0 + + qc.measure(range(7), range(7)) # 0110101 + + backend = self.backend(method=method) + counts = backend.run(qc).result().get_counts() + self.assertEqual(len(counts), 1) + self.assertIn("0110101", counts) + + @data("statevector", "density_matrix", "matrix_product_state", "stabilizer") + def test_bit_xor_operation(self, method): + """test bit-or operation""" + qr = QuantumRegister(7) + cr = ClassicalRegister(7) + qc = QuantumCircuit(qr, cr) + qc.x(0) + qc.x(2) + qc.measure(range(4), range(4)) # 0101 + qc.barrier() + b01 = expr.bit_xor(cr[0], cr[1]) # 1 & 0 -> 1 + with qc.if_test(b01): + qc.x(4) # q4 -> 1 + + b02 = expr.bit_xor(cr[0], cr[2]) # 1 & 1 -> 0 + with qc.if_test(b02): + qc.x(5) # q5 -> 0 + + b13 = expr.bit_xor(cr[1], cr[3]) # 0 & 0 -> 0 + with qc.if_test(b13): + qc.x(6) # q6 -> 0 + + qc.measure(range(7), range(7)) # 0010101 + + backend = self.backend(method=method) + counts = backend.run(qc).result().get_counts() + self.assertEqual(len(counts), 1) + self.assertIn("0010101", counts) diff --git a/test/terra/expression/test_classical_expressions.py b/test/terra/expression/test_classical_expressions.py index 32847579d4..fee05f7a6f 100644 --- a/test/terra/expression/test_classical_expressions.py +++ b/test/terra/expression/test_classical_expressions.py @@ -353,12 +353,19 @@ def test_binary_expression(self): True, ) - # (False & True): error + # (False & True): Uint -> error try: - AerBinaryExpr(AerBinaryOp.BitAnd, AerBoolValue(False), AerBoolValue(True)) + AerBinaryExpr(AerBinaryOp.BitAnd, AerBoolValue(False), AerBoolValue(True)).eval_uint("") self.fail("do not reach here") except Exception: pass + # (False & True) = False + self.assertEqual( + AerBinaryExpr(AerBinaryOp.BitAnd, AerBoolValue(False), AerBoolValue(True)).eval_bool( + "" + ), + False, + ) # (0b001 & 0b001) = 0b001 self.assertEqual( AerBinaryExpr(