|
2 | 2 |
|
3 | 3 | from collections.abc import Sequence
|
4 | 4 |
|
5 |
| -import hugr |
| 5 | +import hugr.std.int |
6 | 6 | from hugr import Wire, ops
|
7 | 7 | from hugr import tys as ht
|
8 | 8 | from hugr.std.float import FLOAT_T
|
@@ -45,45 +45,53 @@ def ine(width: int) -> ops.ExtOp:
|
45 | 45 | return _instantiate_int_op("ine", width, [int_t(width), int_t(width)], [ht.Bool])
|
46 | 46 |
|
47 | 47 |
|
| 48 | +def iwiden_u(from_width: int, to_width: int) -> ops.ExtOp: |
| 49 | + """Returns an unsigned `std.arithmetic.int.widen_u` operation.""" |
| 50 | + return _instantiate_int_op( |
| 51 | + "iwiden_u", [from_width, to_width], [int_t(from_width)], [int_t(to_width)] |
| 52 | + ) |
| 53 | + |
| 54 | + |
| 55 | +def iwiden_s(from_width: int, to_width: int) -> ops.ExtOp: |
| 56 | + """Returns a signed `std.arithmetic.int.widen_s` operation.""" |
| 57 | + return _instantiate_int_op( |
| 58 | + "iwiden_s", [from_width, to_width], [int_t(from_width)], [int_t(to_width)] |
| 59 | + ) |
| 60 | + |
| 61 | + |
48 | 62 | # ------------------------------------------------------
|
49 | 63 | # --------- std.arithmetic.conversions ops -------------
|
50 | 64 | # ------------------------------------------------------
|
51 | 65 |
|
52 | 66 |
|
| 67 | +def _instantiate_convert_op( |
| 68 | + name: str, |
| 69 | + inp: list[ht.Type], |
| 70 | + out: list[ht.Type], |
| 71 | + args: list[ht.TypeArg] | None = None, |
| 72 | +) -> ops.ExtOp: |
| 73 | + op_def = hugr.std.int.CONVERSIONS_EXTENSION.get_op(name) |
| 74 | + return ops.ExtOp(op_def, ht.FunctionType(inp, out), args or []) |
| 75 | + |
| 76 | + |
53 | 77 | def convert_ifromusize() -> ops.ExtOp:
|
54 | 78 | """Returns a `std.arithmetic.conversions.ifromusize` operation."""
|
55 |
| - op_def = hugr.std.int.CONVERSIONS_EXTENSION.get_op("ifromusize") |
56 |
| - return ops.ExtOp( |
57 |
| - op_def, |
58 |
| - ht.FunctionType([ht.USize()], [INT_T]), |
59 |
| - ) |
| 79 | + return _instantiate_convert_op("ifromusize", [ht.USize()], [INT_T]) |
60 | 80 |
|
61 | 81 |
|
62 | 82 | def convert_itousize() -> ops.ExtOp:
|
63 | 83 | """Returns a `std.arithmetic.conversions.itousize` operation."""
|
64 |
| - op_def = hugr.std.int.CONVERSIONS_EXTENSION.get_op("itousize") |
65 |
| - return ops.ExtOp( |
66 |
| - op_def, |
67 |
| - ht.FunctionType([INT_T], [ht.USize()]), |
68 |
| - ) |
| 84 | + return _instantiate_convert_op("itousize", [INT_T], [ht.USize()]) |
69 | 85 |
|
70 | 86 |
|
71 | 87 | def convert_ifrombool() -> ops.ExtOp:
|
72 | 88 | """Returns a `std.arithmetic.conversions.ifrombool` operation."""
|
73 |
| - op_def = hugr.std.int.CONVERSIONS_EXTENSION.get_op("ifrombool") |
74 |
| - return ops.ExtOp( |
75 |
| - op_def, |
76 |
| - ht.FunctionType([ht.Bool], [int_t(1)]), |
77 |
| - ) |
| 89 | + return _instantiate_convert_op("ifrombool", [ht.Bool], [int_t(0)]) |
78 | 90 |
|
79 | 91 |
|
80 | 92 | def convert_itobool() -> ops.ExtOp:
|
81 | 93 | """Returns a `std.arithmetic.conversions.itobool` operation."""
|
82 |
| - op_def = hugr.std.int.CONVERSIONS_EXTENSION.get_op("itobool") |
83 |
| - return ops.ExtOp( |
84 |
| - op_def, |
85 |
| - ht.FunctionType([int_t(1)], [ht.Bool]), |
86 |
| - ) |
| 94 | + return _instantiate_convert_op("itobool", [int_t(0)], [ht.Bool]) |
87 | 95 |
|
88 | 96 |
|
89 | 97 | # ------------------------------------------------------
|
@@ -264,3 +272,35 @@ def compile(self, args: list[Wire]) -> list[Wire]:
|
264 | 272 | ht.FunctionType([FLOAT_T] * len(args), [FLOAT_T]),
|
265 | 273 | )
|
266 | 274 | return list(self.builder.add(ops.MakeTuple()(div, mod)))
|
| 275 | + |
| 276 | + |
| 277 | +class IToBoolCompiler(CustomCallCompiler): |
| 278 | + """Compiler for the `Int` and `Nat` `.__bool__` methods. |
| 279 | +
|
| 280 | + Note that the native `std.arithmetic.conversions.itobool` hugr op |
| 281 | + only supports 1 bit integers as input. |
| 282 | + """ |
| 283 | + |
| 284 | + def compile(self, args: list[Wire]) -> list[Wire]: |
| 285 | + # Emit a comparison against zero |
| 286 | + [num] = args |
| 287 | + zero = self.builder.load(hugr.std.int.IntVal(0, width=6)) |
| 288 | + out = self.builder.add_op(ine(NumericType.INT_WIDTH), num, zero) |
| 289 | + return [out] |
| 290 | + |
| 291 | + |
| 292 | +class IFromBoolCompiler(CustomCallCompiler): |
| 293 | + """Compiler for the `Bool` `.__int__` and `.__nat__` methods. |
| 294 | +
|
| 295 | + Note that the native `std.arithmetic.conversions.ifrombool` hugr op |
| 296 | + only produces 1 bit integers as output, so we have to widen the result. |
| 297 | + """ |
| 298 | + |
| 299 | + def compile(self, args: list[Wire]) -> list[Wire]: |
| 300 | + # Emit an `ifrombool` followed by a widening cast |
| 301 | + # We use `widen_u` independently of the target type, since we want the bit `1` |
| 302 | + # to be expanded to `0x00000001` even for `nat` types |
| 303 | + [boolean] = args |
| 304 | + bit = self.builder.add_op(convert_ifrombool(), boolean) |
| 305 | + num = self.builder.add_op(iwiden_u(0, NumericType.INT_WIDTH), bit) |
| 306 | + return [num] |
0 commit comments