Skip to main content

ket/c_api/
block.rs

1// SPDX-FileCopyrightText: 2026 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5#![allow(clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref)]
6
7//! C API for interacting with `BasicBlock` operations.
8
9use std::ffi::{c_char, CString};
10
11use crate::{
12    c_api::c_ok,
13    error::KetError,
14    ir::{block::BasicBlock, gate::QuantumGate},
15};
16
17/// Allocates a new, empty [`BasicBlock`] and writes its pointer to `block`.
18#[no_mangle]
19pub extern "C" fn ket_block_new(block: &mut *mut BasicBlock) -> i32 {
20    *block = Box::into_raw(Box::new(BasicBlock::new()));
21    c_ok()
22}
23
24/// Deallocates the memory associated with a [`BasicBlock`].
25#[no_mangle]
26pub extern "C" fn ket_block_delete(block: *mut BasicBlock) -> i32 {
27    let _ = unsafe { *Box::from_raw(block) };
28    c_ok()
29}
30
31/// Appends a new quantum gate (provided as a JSON payload) to a [`BasicBlock`].
32#[no_mangle]
33pub extern "C" fn ket_block_append_gate(
34    block: &mut BasicBlock,
35    gate_json: *const c_char,
36    target: usize,
37) -> i32 {
38    let gate = from_json!(gate_json, QuantumGate);
39    block.append_gate(gate, target);
40    c_ok()
41}
42
43/// Creates a new [`BasicBlock`] that is the adjoint (inverse) of the provided block.
44#[no_mangle]
45pub extern "C" fn ket_block_inverse(
46    block: &BasicBlock,
47    inverted_block: &mut *mut BasicBlock,
48) -> i32 {
49    *inverted_block = Box::into_raw(Box::new(block.inverse()));
50    c_ok()
51}
52
53/// Creates a new [`BasicBlock`] resulting from adding control qubits to all gates in the block.
54#[no_mangle]
55pub extern "C" fn ket_block_control(
56    block: &BasicBlock,
57    control_qubits: *const usize,
58    control_qubits_len: usize,
59    controlled_block: &mut *mut BasicBlock,
60) -> i32 {
61    let qubits = unsafe { std::slice::from_raw_parts(control_qubits, control_qubits_len) };
62    match block.control(qubits) {
63        Ok(block) => {
64            *controlled_block = Box::into_raw(Box::new(block));
65            c_ok()
66        }
67        Err(err) => err.error_code(),
68    }
69}
70
71/// Enables approximate decomposition strategies for all gates in the given [`BasicBlock`].
72#[no_mangle]
73pub extern "C" fn ket_block_enable_approximated_decomposition(block: &mut BasicBlock) -> i32 {
74    block.enable_approximated_decomposition();
75    c_ok()
76}
77
78/// Locks the control qubits of all gates in the given [`BasicBlock`], preventing further additions.
79#[no_mangle]
80pub extern "C" fn ket_block_lock_control(block: &mut BasicBlock) -> i32 {
81    block.lock_control();
82    c_ok()
83}
84
85/// Appends the contents of `other` block to `block` and consumes `other`.
86#[no_mangle]
87pub extern "C" fn ket_block_append_block(block: &mut BasicBlock, other: *mut BasicBlock) -> i32 {
88    let other = unsafe { Box::from_raw(other) };
89    block.append_block(*other, None);
90    c_ok()
91}
92
93/// Adds a global phase to the [`BasicBlock`].
94#[no_mangle]
95pub extern "C" fn ket_block_add_global_phase(block: &mut BasicBlock, phase: f64) -> i32 {
96    block.add_global_phase(phase);
97    c_ok()
98}
99
100/// Serializes the properties of the [`BasicBlock`] into a JSON payload and writes it to the buffer.
101#[no_mangle]
102pub extern "C" fn ket_block_proprieties_json(
103    block: &BasicBlock,
104    proprieties: &mut *const c_char,
105) -> i32 {
106    *proprieties = to_json!(&block.qubits_op).into_raw();
107
108    c_ok()
109}
110
111/// Marks the [`BasicBlock`] as implementing a diagonal gate.
112#[no_mangle]
113pub extern "C" fn ket_block_set_as_diagonal(block: &mut BasicBlock) -> i32 {
114    block.set_as_diagonal();
115
116    c_ok()
117}
118
119/// Marks the [`BasicBlock`] as implementing a permutation gate.
120#[no_mangle]
121pub extern "C" fn ket_block_set_as_permutation(block: &mut BasicBlock) -> i32 {
122    block.set_as_permutation();
123
124    c_ok()
125}