Skip to content

Classical expression Value does not store data correctly #15269

@gadial

Description

@gadial

Environment

  • Qiskit version: 2.2
  • Python version: 3.13
  • Operating system: Linux

What is happening?

when expr.Value is of type Uint it is expected to have unbounded precision. When it was implemented in Python, this was the case automatically; in Rust the value is converted to f64 when it is too big, causing precision loss.

How can we reproduce the issue?

from qiskit.circuit.classical import expr, types
n = 10
val = expr.Value(n, types.Uint(1)),
print(val[0].value == n) # returns True
n = 100000000000000000000000000000000000
val = expr.Value(n, types.Uint(1)),
print(val[0].value == n) # returns False

What should happen?

The code above should return True in both cases; the integer value should be stored as an unbounded sequence of bytes.

Any suggestions?

The QPY component already had this problem and solved it:

        elif isinstance(node.value, int):
            self.file_obj.write(type_keys.ExprValue.INT)
            if node.value == 0:
                num_bytes = 0
                buffer = b""
            else:
                # This wastes a byte for `-(2 ** (8*n - 1))` for natural `n`, but they'll still
                # decode fine so it's not worth another special case.  They'll encode to
                # b"\xff\x80\x00\x00...", but we could encode them to b"\x80\x00\x00...".
                num_bytes = (node.value.bit_length() // 8) + 1
                buffer = node.value.to_bytes(num_bytes, "big", signed=True)
            self.file_obj.write(
                struct.pack(formats.EXPR_VALUE_INT_PACK, *formats.EXPR_VALUE_INT(num_bytes))
            )
            self.file_obj.write(buffer)

This can be done easily in Value.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status

Ready

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions