qrisp.gidney_cq_venting_adder#

gidney_cq_venting_adder(d: int | BigInteger, target: QuantumVariable, c_in: QuantumBool | None = None, c_out: QuantumBool | None = None, ctrl: QuantumVariable | QuantumBool | None = None) None[source]#

In-place classical-quantum adder using Gidney’s carry-venting technique.

Adds a classical integer \(d\) and an optional carry-in \(c_{\text{in}}\) to a quantum register, storing the result back in the same register.

Uses 3 clean ancillae (allocated internally) and no external dirty workspace. The target register is split in half — each half serves as dirty storage for the other half’s carry chain — keeping the total qubit count to n + 3. For registers with fewer than 6 qubits the split-half path is replaced by gidney_adder() (unitary, no vents), which avoids a nested-q_cond tracing-session issue for n=5. This matches the paper’s strategy of using a clean adder when enough ancillae are available.

Heavily adapted from the reference implementation released with arXiv:2507.23079 at https://zenodo.org/records/15866587.

Warning

This function requires dynamic (JASP) mode and does not work in static circuit generation, because it relies on mid-circuit measurements (venting) whose outcomes determine subsequent operations.

Parameters:
targetQuantumVariable

Target register, little-endian (index 0 = LSB). Modified in place.

dint or BigInteger

Classical addend (compile-time constant).

c_inQuantumBool | None

Quantum carry-in. None is treated as \(\ket{0}\).

Returns:
None
Raises:
TypeError

If d is a QuantumVariable or list (must be a classical integer).

TypeError

If target is not a QuantumVariable.

RuntimeError

If called outside dynamic (JASP) tracing mode.

Examples

Basic addition in dynamic (JASP) mode:

from qrisp import QuantumFloat, measure, gidney_cq_venting_adder
from qrisp.jasp import jaspify

@jaspify
def main():
    target = QuantumFloat(5)
    target[:] = 2
    gidney_cq_venting_adder(7, target)
    return measure(target)

result = main()
# result is 9 (2 + 7 = 9)

Addition with a carry-in qubit:

@jaspify
def main():
    target = QuantumFloat(4)
    target[:] = 5
    c_in = QuantumFloat(1)
    c_in[:] = 1
    gidney_cq_venting_adder(2, target, c_in=c_in[0])
    return measure(target)

result = main()
# result is 8 (5 + 2 + carry_in = 8)

Controlled addition (zero extra Toffoli cost):

from qrisp import control, QuantumBool

@jaspify
def main():
    target = QuantumFloat(5)
    target[:] = 10
    ctrl = QuantumBool()
    ctrl[:] = 1
    with control(ctrl):
        gidney_cq_venting_adder(5, target)
    return measure(target)

result = main()
# result is 15 (10 + 5 = 15)
# when ctrl is not provided, target stays unchanged