Skip to content

Commit ddffe17

Browse files
authored
Add shift and bitwise operations (#31)
* Add shift and logical operations * Add logical OR and AND --------- Co-authored-by: Mitch D'Ewart <[email protected]>
1 parent 04ea000 commit ddffe17

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

oqpy/base.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,36 @@ def __pow__(self, other: AstConvertible) -> OQPyBinaryExpression:
107107
def __rpow__(self, other: AstConvertible) -> OQPyBinaryExpression:
108108
return self._to_binary("**", other, self)
109109

110+
def __lshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
111+
return self._to_binary("<<", self, other)
112+
113+
def __rlshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
114+
return self._to_binary("<<", other, self)
115+
116+
def __rshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
117+
return self._to_binary(">>", self, other)
118+
119+
def __rrshift__(self, other: AstConvertible) -> OQPyBinaryExpression:
120+
return self._to_binary(">>", other, self)
121+
122+
def __and__(self, other: AstConvertible) -> OQPyBinaryExpression:
123+
return self._to_binary("&", self, other)
124+
125+
def __rand__(self, other: AstConvertible) -> OQPyBinaryExpression:
126+
return self._to_binary("&", other, self)
127+
128+
def __or__(self, other: AstConvertible) -> OQPyBinaryExpression:
129+
return self._to_binary("|", self, other)
130+
131+
def __ror__(self, other: AstConvertible) -> OQPyBinaryExpression:
132+
return self._to_binary("|", other, self)
133+
134+
def __xor__(self, other: AstConvertible) -> OQPyBinaryExpression:
135+
return self._to_binary("^", self, other)
136+
137+
def __rxor__(self, other: AstConvertible) -> OQPyBinaryExpression:
138+
return self._to_binary("^", other, self)
139+
110140
def __eq__(self, other: AstConvertible) -> OQPyBinaryExpression: # type: ignore[override]
111141
return self._to_binary("==", self, other)
112142

@@ -125,13 +155,26 @@ def __ge__(self, other: AstConvertible) -> OQPyBinaryExpression:
125155
def __le__(self, other: AstConvertible) -> OQPyBinaryExpression:
126156
return self._to_binary("<=", self, other)
127157

158+
def __invert__(self) -> OQPyUnaryExpression:
159+
return self._to_unary("~", self)
160+
128161
def __bool__(self) -> bool:
129162
raise RuntimeError(
130163
"OQPy expressions cannot be converted to bool. This can occur if you try to check "
131164
"the equality of expressions using == instead of expr_matches."
132165
)
133166

134167

168+
def logical_and(first: AstConvertible, second: AstConvertible) -> OQPyBinaryExpression:
169+
"""Logical AND."""
170+
return OQPyBinaryExpression(ast.BinaryOperator["&&"], first, second)
171+
172+
173+
def logical_or(first: AstConvertible, second: AstConvertible) -> OQPyBinaryExpression:
174+
"""Logical OR."""
175+
return OQPyBinaryExpression(ast.BinaryOperator["||"], first, second)
176+
177+
135178
def expr_matches(a: Any, b: Any) -> bool:
136179
"""Check equality of the given objects.
137180

tests/test_directives.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import oqpy
2626
from oqpy import *
27-
from oqpy.base import expr_matches
27+
from oqpy.base import expr_matches, logical_and, logical_or
2828
from oqpy.quantum_types import PhysicalQubits
2929
from oqpy.timing import OQDurationLiteral
3030

@@ -269,22 +269,68 @@ def test_binary_expressions():
269269
prog = Program()
270270
i = IntVar(5, "i")
271271
j = IntVar(2, "j")
272+
k = IntVar(0, "k")
273+
b1 = BoolVar(False, "b1")
274+
b2 = BoolVar(True, "b2")
275+
b3 = BoolVar(False, "b3")
272276
prog.set(i, 2 * (i + j))
273277
prog.set(j, 2 % (2 - i) % 2)
274278
prog.set(j, 1 + oqpy.pi)
275279
prog.set(j, 1 / oqpy.pi**2 / 2 + 2**oqpy.pi)
276280
prog.set(j, -oqpy.pi * oqpy.pi - i**j)
281+
prog.set(k, i & 51966)
282+
prog.set(k, 51966 & i)
283+
prog.set(k, i & j)
284+
prog.set(k, i | 51966)
285+
prog.set(k, 51966 | i)
286+
prog.set(k, i | j)
287+
prog.set(k, i ^ 51966)
288+
prog.set(k, 51966 & i)
289+
prog.set(k, i ^ j)
290+
prog.set(k, i >> 1)
291+
prog.set(k, 1 >> i)
292+
prog.set(k, i >> j)
293+
prog.set(k, i << 1)
294+
prog.set(k, 1 << j)
295+
prog.set(k, i << j)
296+
prog.set(k, ~k)
297+
prog.set(b1, logical_or(b2, b3))
298+
prog.set(b1, logical_and(b2, True))
299+
prog.set(b1, logical_or(False, b3))
277300

278301
expected = textwrap.dedent(
279302
"""
280303
OPENQASM 3.0;
281304
int[32] i = 5;
282305
int[32] j = 2;
306+
int[32] k = 0;
307+
bool b1 = false;
308+
bool b2 = true;
309+
bool b3 = false;
283310
i = 2 * (i + j);
284311
j = 2 % (2 - i) % 2;
285312
j = 1 + pi;
286313
j = 1 / pi ** 2 / 2 + 2 ** pi;
287314
j = -pi * pi - i ** j;
315+
k = i & 51966;
316+
k = 51966 & i;
317+
k = i & j;
318+
k = i | 51966;
319+
k = 51966 | i;
320+
k = i | j;
321+
k = i ^ 51966;
322+
k = 51966 & i;
323+
k = i ^ j;
324+
k = i >> 1;
325+
k = 1 >> i;
326+
k = i >> j;
327+
k = i << 1;
328+
k = 1 << j;
329+
k = i << j;
330+
k = ~k;
331+
b1 = b2 || b3;
332+
b1 = b2 && true;
333+
b1 = false || b3;
288334
"""
289335
).strip()
290336

0 commit comments

Comments
 (0)