5. Quantum Intrinsic Operations

In an effort to support low-level quantum programming and build foundational quantum kernels for large-scale applications, CUDA Quantum defines the quantum intrinsic operation as an abstraction for device-specific single-qudit unitary operations. A quantum intrinsic operation is modeled via a standard C++ function with a unique instruction name and general function operands. These operands can model classical rotation parameters or units of quantum information (e.g. the cudaq::qudit). The syntax for these operations is

void INST_NAME( PARAM...?, qudit<N>&...);

where INST_NAME is the name of the instruction, qudit<N>&... indicates one many cudaq::qudit instances, and PARAM...? indicates optional parameters of floating point type (e.g. double, float). All intrinsic operations should start with a base declaration targeting a single cudaq::qudit, and overloads should be provided that take more than one cudaq::qudit instances to model the application of that instruction on all provided cudaq::qudits, e.g. void x(cudaq::qubit&) and x(cudaq::qubit&, cudaq::qubit&, cudaq::qubit&), modeling the NOT operation on a single cudaq::qubit or on multiple cudaq::qubit.

Implementations should provide overloads to support broadcasting of single-qubit intrinsic operations across a register of cudaq::qudit. For example, x(cudaq::qvector<>&) should apply a NOT operation on all cudaq::qubit in the provided cudaq::qvector. A set of quantum intrinsic operations for the cudaq::qubit then for example looks as follows, where NAME, ROTATION_NAME, and MEASURE_OP stand for the names of single-qubit operations, single-qubit rotations, and measurement operations respectively:

  namespace cudaq {
    struct base;
    struct ctrl;
    struct adj;

    // Single qubit operations, ctrl / adj variants, and broadcasting
    template<typename mod = base, typename... QubitArgs>
    void NAME(QubitArgs&... args) noexcept { ... }

    template<typename mod = base>
    void NAME(const qvector& qr) noexcept { ... }

    template<typename mod = ctrl>
    void NAME(qvector& ctrls, qubit& target) noexcept { ... }

    // Single qubit rotation operations and ctrl / adj variants
    template <typename mod = base, typename ScalarAngle, typename... QubitArgs>
    void ROTATION_NAME(ScalarAngle angle, QubitArgs &...args) noexcept { ... }

    bool MEASURE_OP(qubit &q) noexcept;
    std::vector<bool> MEASURE_OP(qvector &q) noexcept;
    double measure(cudaq::spin_op & term) noexcept { ... }

The set of gates that the official CUDA Quantum implementation supports can be found in the API documentation.