ket/c_api/
process.rs

1// SPDX-FileCopyrightText: 2020 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2// SPDX-FileCopyrightText: 2020 Rafael de Santiago <r.santiago@ufsc.br>
3//
4// SPDX-License-Identifier: Apache-2.0
5
6//! C API for the `Process` struct.
7
8use itertools::Itertools;
9
10use super::error::wrapper;
11use crate::{
12    execution::QuantumExecution,
13    ir::{
14        gate::Param,
15        qubit::{LogicalQubit, Qubit},
16    },
17    prelude::*,
18};
19
20/// Creates a new `Process` instance with the given process ID.
21///
22/// # Arguments
23///
24/// * `config` -  \[in\] A mutable pointer to a `Configuration` instance.
25/// * `process` -  \[out\] A mutable pointer to a `Process` pointer.
26///
27/// # Returns
28///
29/// An integer representing the error code. `0` indicates success.
30///
31/// # Safety
32///
33/// This function is marked as unsafe because it deals with raw pointers.
34#[no_mangle]
35pub unsafe extern "C" fn ket_process_new(
36    config: *mut (ExecutionTarget, Option<QuantumExecution>),
37    process: &mut *mut Process,
38) -> i32 {
39    let (execution_target, execution) = unsafe { *Box::from_raw(config) };
40    *process = Box::into_raw(Box::new(Process::new(execution_target, execution)));
41    KetError::Success.error_code()
42}
43
44/// Deletes the `Process` instance.
45///
46/// # Arguments
47///
48/// * `process` -  \[in\] A pointer to the `Process` instance to be deleted.
49///
50/// # Returns
51///
52/// An integer representing the error code. `0` indicates success.
53///
54/// # Safety
55///
56/// This function is marked as unsafe because it deals with raw pointers.
57#[no_mangle]
58pub unsafe extern "C" fn ket_process_delete(process: *mut Process) -> i32 {
59    unsafe {
60        let _ = Box::from_raw(process);
61    }
62    KetError::Success.error_code()
63}
64
65/// Allocates a qubit for the `Process` instance.
66///
67/// # Arguments
68///
69/// * `process` -  \[in\] A mutable reference to the `Process` instance.
70/// * `qubit` -  \[out\] A mutable pointer to a `usize`.
71///
72/// # Returns
73///
74/// An integer representing the error code. `0` indicates success.
75#[no_mangle]
76pub extern "C" fn ket_process_allocate_qubit(process: &mut Process, qubit: &mut usize) -> i32 {
77    match process.alloc() {
78        Ok(result) => {
79            *qubit = result.index();
80            KetError::Success.error_code()
81        }
82        Err(error) => error.error_code(),
83    }
84}
85
86/// Applies a quantum gate to the target `Qubit` in the `Process` instance.
87///
88/// # Arguments
89///
90/// * `process` -  \[in\] A mutable reference to the `Process` instance.
91/// * `gate` -  \[in\] An integer representing the gate type. See the function body for the mapping of gate values to gate types.
92/// * `pi_fraction_top` -  \[in\] The numerator of the fraction part of the angle, used by certain gate types.
93/// * `pi_fraction_bottom` -  \[in\] The denominator of the fraction part of the angle, used by certain gate types.
94/// * `scalar` -  \[in\] A floating-point parameter value used by certain gate types.
95/// * `target` -  \[in\] A reference to the target `Qubit` instance.
96///
97/// # Returns
98///
99/// An integer representing the error code. `0` indicates success.
100#[no_mangle]
101pub extern "C" fn ket_process_apply_gate(
102    process: &mut Process,
103    gate: i32,
104    angle: f64,
105    use_param: bool,
106    param_index: usize,
107    target: usize,
108) -> i32 {
109    let gate = match gate {
110        1 => QuantumGate::PauliX,
111        2 => QuantumGate::PauliY,
112        3 => QuantumGate::PauliZ,
113        10 => QuantumGate::RotationX(if use_param {
114            Param::new_ref(param_index, angle)
115        } else {
116            angle.into()
117        }),
118        20 => QuantumGate::RotationY(if use_param {
119            Param::new_ref(param_index, angle)
120        } else {
121            angle.into()
122        }),
123        30 => QuantumGate::RotationZ(if use_param {
124            Param::new_ref(param_index, angle)
125        } else {
126            angle.into()
127        }),
128        31 => QuantumGate::Phase(if use_param {
129            Param::new_ref(param_index, angle)
130        } else {
131            angle.into()
132        }),
133        0 => QuantumGate::Hadamard,
134        _ => panic!("Undefined Pauli index. Use 0 for H, 1 for X, 2 for Y, and 3 for Z"),
135    };
136
137    wrapper(process.gate(gate, LogicalQubit::main(target)))
138}
139
140/// Applies a global phase.
141///
142/// # Arguments
143///
144/// * `process` -  \[in\] A mutable reference to the `Process` instance.
145/// * `pi_fraction_top` -  \[in\] The numerator of the fraction part of the angle.
146/// * `pi_fraction_bottom` -  \[in\] The denominator of the fraction part of the angle.
147/// * `scalar` -  \[in\] A floating-point parameter value.
148///
149/// # Returns
150///
151/// An integer representing the error code. `0` indicates success.
152#[no_mangle]
153pub extern "C" fn ket_process_apply_global_phase(process: &mut Process, angle: f64) -> i32 {
154    wrapper(process.global_phase(angle))
155}
156
157/// Measures the specified qubits in the `Process` instance.
158///
159/// # Arguments
160///
161/// * `process` -  \[in\] A mutable reference to the `Process` instance.
162/// * `qubits` -  \[in\] A mutable pointer to an array of mutable references to `Qubit` instances.
163/// * `qubits_size` -  \[in\] The size of the `qubits` array.
164/// * `result` -  \[out\] A mutable pointer to a `usize` where the measurement result will be stored.
165///
166/// # Returns
167///
168/// An integer representing the error code. `0` indicates success.
169///
170/// # Safety
171///
172/// This function is marked as unsafe due to the use of raw pointers.
173#[no_mangle]
174pub unsafe extern "C" fn ket_process_measure(
175    process: &mut Process,
176    qubits: *const usize,
177    qubits_size: usize,
178    result: &mut usize,
179) -> i32 {
180    let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
181    let qubits = qubits
182        .iter()
183        .map(|index| LogicalQubit::main(*index))
184        .collect::<Vec<_>>();
185
186    match process.measure(&qubits) {
187        Ok(result_id) => {
188            *result = result_id;
189            KetError::Success.error_code()
190        }
191        Err(error) => error.error_code(),
192    }
193}
194
195/// Creates a new `PauliHamiltonian` instance.
196///
197/// # Arguments
198///
199/// * `hamiltonian` -  \[out\] A mutable pointer to a `PauliHamiltonian` pointer.
200///
201/// # Returns
202///
203/// An integer representing the error code. `0` indicates success.
204#[no_mangle]
205pub extern "C" fn ket_hamiltonian_new(hamiltonian: &mut *mut Hamiltonian<LogicalQubit>) -> i32 {
206    *hamiltonian = Box::into_raw(Box::default());
207
208    KetError::Success.error_code()
209}
210
211/// Adds a term to the `PauliHamiltonian`.
212///
213/// # Arguments
214///
215/// * `hamiltonian` -  \[in\] A mutable reference to the `PauliHamiltonian` instance.
216/// * `pauli` -  \[in\] A pointer to an array of integers representing the Pauli operators (1 for X, 2 for Y, 3 for Z).
217/// * `pauli_size` -  \[in\] The size of the `pauli` array.
218/// * `qubits` -  \[in\] A pointer to an array of integers representing the qubit indices for each Pauli operator.
219/// * `qubits_size` -  \[in\] The size of the `qubits` array.
220/// * `coefficients` -  \[in\] The coefficient for the term.
221///
222/// # Returns
223///
224/// An integer representing the error code. `0` indicates success.
225///
226/// # Safety
227///
228/// This function is marked as unsafe due to the use of raw pointers.
229#[no_mangle]
230pub unsafe extern "C" fn ket_hamiltonian_add(
231    hamiltonian: &mut Hamiltonian<LogicalQubit>,
232    pauli: *const i32,
233    pauli_size: usize,
234    qubits: *const usize,
235    qubits_size: usize,
236    coefficients: f64,
237) -> i32 {
238    assert_eq!(pauli_size, qubits_size);
239
240    let pauli = unsafe { std::slice::from_raw_parts(pauli, pauli_size) };
241    let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
242    let qubits = qubits
243        .iter()
244        .map(|index| LogicalQubit::main(*index))
245        .collect::<Vec<_>>();
246
247    let pauli_product: PauliProduct<_> = pauli
248        .iter()
249        .zip(qubits.iter())
250        .map(|(pauli, qubit)| {
251            let pauli = match pauli {
252                1 => Pauli::PauliX,
253                2 => Pauli::PauliY,
254                3 => Pauli::PauliZ,
255                _ => panic!("Undefined Pauli index. Use 1 for X, 2 for Y, and 3 for Z"),
256            };
257
258            PauliTerm {
259                pauli,
260                qubit: *qubit,
261            }
262        })
263        .collect();
264
265    hamiltonian.products.push(pauli_product);
266    hamiltonian.coefficients.push(coefficients);
267
268    KetError::Success.error_code()
269}
270
271/// Calculates the expected value of the `PauliHamiltonian` in the `Process` instance.
272///
273/// # Arguments
274///
275/// * `process` -  \[in\] A mutable reference to the `Process` instance.
276/// * `hamiltonian` -  \[in\] A mutable pointer to a `PauliHamiltonian`.
277/// * `result` -  \[out\] A mutable pointer to a `usize` where the result identifier will be stored.
278///
279/// # Returns
280///
281/// An integer representing the error code. `0` indicates success.
282///
283/// # Safety
284///
285/// This function is marked as unsafe due to the use of raw pointers.
286#[no_mangle]
287pub unsafe extern "C" fn ket_process_exp_value(
288    process: &mut Process,
289    hamiltonian: *mut Hamiltonian<LogicalQubit>,
290    result: &mut usize,
291) -> i32 {
292    let hamiltonian = unsafe { Box::from_raw(hamiltonian) };
293    match process.exp_value(*hamiltonian) {
294        Ok(result_id) => {
295            *result = result_id;
296
297            KetError::Success.error_code()
298        }
299        Err(error) => error.error_code(),
300    }
301}
302
303/// Samples the specified qubits in the `Process` instance.
304///
305/// # Arguments
306///
307/// * `process` -  \[in\] A mutable reference to the `Process` instance.
308/// * `qubits` -  \[in\] A pointer to an array of integers representing the qubit indices to be sampled.
309/// * `qubits_size` -  \[in\] The size of the `qubits` array.
310/// * `shots` -  \[in\] The number of measurement shots.
311/// * `result` -  \[out\] A mutable pointer to a `usize` where the result identifier will be stored.
312///
313/// # Returns
314///
315/// An integer representing the error code. `0` indicates success.
316///
317/// # Safety
318///
319/// This function is marked as unsafe due to the use of raw pointers.
320#[no_mangle]
321pub unsafe extern "C" fn ket_process_sample(
322    process: &mut Process,
323    qubits: *const usize,
324    qubits_size: usize,
325    shots: usize,
326    result: &mut usize,
327) -> i32 {
328    let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
329    let qubits = qubits
330        .iter()
331        .map(|index| LogicalQubit::main(*index))
332        .collect::<Vec<_>>();
333
334    match process.sample(&qubits, shots) {
335        Ok(result_id) => {
336            *result = result_id;
337
338            KetError::Success.error_code()
339        }
340        Err(error) => error.error_code(),
341    }
342}
343
344/// Dumps the state of the specified qubits in the `Process` instance.
345///
346/// # Arguments
347///
348/// * `process` -  \[in\] A mutable reference to the `Process` instance.
349/// * `qubits` -  \[in\] A pointer to an array of qubit indices to be dumped.
350/// * `qubits_size` -  \[in\] The size of the `qubits` array.
351/// * `result` -  \[out\] A mutable pointer to a `usize` representing the result index of the dump.
352///
353/// # Returns
354///
355/// An integer representing the error code. `0` indicates success.
356///
357/// # Safety
358///
359/// This function is marked as unsafe due to the use of raw pointers.
360#[no_mangle]
361pub unsafe extern "C" fn ket_process_dump(
362    process: &mut Process,
363    qubits: *const usize,
364    qubits_size: usize,
365    result: &mut usize,
366) -> i32 {
367    let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
368    let qubits = qubits
369        .iter()
370        .map(|index| LogicalQubit::main(*index))
371        .collect::<Vec<_>>();
372
373    match process.dump(&qubits) {
374        Ok(result_id) => {
375            *result = result_id;
376
377            KetError::Success.error_code()
378        }
379        Err(error) => error.error_code(),
380    }
381}
382
383/// Pushes control qubits onto the control stack in the `Process` instance.
384///
385/// # Arguments
386///
387/// * `process` -  \[in\] A mutable reference to the `Process` instance.
388/// * `qubits` -  \[in\] A pointer to an array of qubit indices to be pushed onto the control stack.
389/// * `qubits_size` -  \[in\] The size of the `qubits` array.
390///
391/// # Returns
392///
393/// An integer representing the error code. `0` indicates success.
394///
395/// # Safety
396///
397/// This function is marked as unsafe due to the use of raw pointers.
398#[no_mangle]
399pub unsafe extern "C" fn ket_process_ctrl_push(
400    process: &mut Process,
401    qubits: *const usize,
402    qubits_size: usize,
403) -> i32 {
404    let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
405    let qubits = qubits
406        .iter()
407        .map(|index| LogicalQubit::main(*index))
408        .collect::<Vec<_>>();
409
410    wrapper(process.ctrl_push(&qubits))
411}
412
413/// Pops control qubits from the control stack in the `Process` instance.
414///
415/// # Arguments
416///
417/// * `process` -  \[in\] A mutable reference to the `Process` instance.
418///
419/// # Returns
420///
421/// An integer representing the error code. `0` indicates success.
422#[no_mangle]
423pub extern "C" fn ket_process_ctrl_pop(process: &mut Process) -> i32 {
424    wrapper(process.ctrl_pop())
425}
426
427/// Pushes control stack in the `Process` instance.
428///
429/// # Arguments
430///
431/// * `process` -  \[in\] A mutable reference to the `Process` instance.
432///
433/// # Returns
434///
435/// An integer representing the error code. `0` indicates success.
436///
437/// # Safety
438///
439/// This function is marked as unsafe due to the use of raw pointers.
440#[no_mangle]
441pub unsafe extern "C" fn ket_process_ctrl_stack(process: &mut Process) -> i32 {
442    wrapper(process.ctrl_begin())
443}
444
445/// Pops control stack from the `Process` instance.
446///
447/// # Arguments
448///
449/// * `process` -  \[in\] A mutable reference to the `Process` instance.
450///
451/// # Returns
452///
453/// An integer representing the error code. `0` indicates success.
454#[no_mangle]
455pub extern "C" fn ket_process_ctrl_unstack(process: &mut Process) -> i32 {
456    wrapper(process.ctrl_end())
457}
458
459/// Begins an adjoint operation in the `Process` instance.
460///
461/// # Arguments
462///
463/// * `process` -  \[in\] A mutable reference to the `Process` instance.
464///
465/// # Returns
466///
467/// An integer representing the error code. `0` indicates success.
468#[no_mangle]
469pub extern "C" fn ket_process_adj_begin(process: &mut Process) -> i32 {
470    wrapper(process.adj_begin())
471}
472
473/// Ends an adjoint operation in the `Process` instance.
474///
475/// # Arguments
476///
477/// * `process` -  \[in\] A mutable reference to the `Process` instance.
478///
479/// # Returns
480///
481/// An integer representing the error code. `0` indicates success.
482#[no_mangle]
483pub extern "C" fn ket_process_adj_end(process: &mut Process) -> i32 {
484    wrapper(process.adj_end())
485}
486
487/// Execute the `Process`.
488///
489/// # Arguments
490///
491/// * `process` -  \[in\] A mutable reference to the `Process` instance.
492///
493/// # Returns
494///
495/// An integer representing the error code. `0` indicates success.
496#[no_mangle]
497pub extern "C" fn ket_process_execute(process: &mut Process) -> i32 {
498    wrapper(process.execute())
499}
500
501/// Prepares the `Process` instance for execution.
502///
503/// # Arguments
504///
505/// * `process` -  \[in\] A mutable reference to the `Process` instance.
506///
507/// # Returns
508///
509/// An integer representing the error code. `0` indicates success.
510#[no_mangle]
511pub extern "C" fn ket_process_prepare_for_execution(process: &mut Process) -> i32 {
512    wrapper(process.prepare_for_execution())
513}
514
515/// Gets the JSON representation of the logical instructions in the `Process` instance.
516///
517/// # Arguments
518///
519/// * `process` -  \[in\] A mutable reference to the `Process` instance.
520/// * `buffer` -  \[in/out\] A mutable pointer to a buffer to store the JSON representation.
521/// * `buffer_size` -  \[in\] The size of the provided buffer.
522/// * `write_size` -  \[out\] A mutable pointer to the actual size of the written data.
523///
524/// # Returns
525///
526/// An integer representing the error code. `0` indicates success.
527///
528/// # Safety
529///
530/// This function is marked as unsafe due to the use of raw pointers.
531#[no_mangle]
532pub unsafe extern "C" fn ket_process_instructions_json(
533    process: &mut Process,
534    buffer: *mut u8,
535    buffer_size: usize,
536    write_size: &mut usize,
537) -> i32 {
538    let instructions = process.instructions_json();
539    let instructions = instructions.as_bytes();
540    *write_size = instructions.len();
541    if buffer_size >= *write_size {
542        let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
543        buffer[..*write_size].copy_from_slice(instructions);
544    }
545
546    KetError::Success.error_code()
547}
548
549/// Gets the JSON representation of the physical instructions in the `Process` instance.
550///
551/// # Arguments
552///
553/// * `process` -  \[in\] A mutable reference to the `Process` instance.
554/// * `buffer` -  \[in/out\] A mutable pointer to a buffer to store the JSON representation.
555/// * `buffer_size` -  \[in\] The size of the provided buffer.
556/// * `write_size` -  \[out\] A mutable pointer to the actual size of the written data.
557///
558/// # Returns
559///
560/// An integer representing the error code. `0` indicates success.
561///
562/// # Safety
563///
564/// This function is marked as unsafe due to the use of raw pointers.
565#[no_mangle]
566pub unsafe extern "C" fn ket_process_isa_instructions_json(
567    process: &mut Process,
568    buffer: *mut u8,
569    buffer_size: usize,
570    write_size: &mut usize,
571) -> i32 {
572    let instructions = process.isa_instructions_json();
573    let instructions = instructions.as_bytes();
574    *write_size = instructions.len();
575    if buffer_size >= *write_size {
576        let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
577        buffer[..*write_size].copy_from_slice(instructions);
578    }
579
580    KetError::Success.error_code()
581}
582
583/// Gets the JSON representation of the metadata in the `Process` instance.
584///
585/// # Arguments
586///
587/// * `process` -  \[in\] A mutable reference to the `Process` instance.
588/// * `buffer` -  \[in/out\] A mutable pointer to a buffer to store the JSON representation.
589/// * `buffer_size` -  \[in\] The size of the provided buffer.
590/// * `write_size` -  \[out\] A mutable pointer to the actual size of the written data.
591///
592/// # Returns
593///
594/// An integer representing the error code. `0` indicates success.
595///
596/// # Safety
597///
598/// This function is marked as unsafe due to the use of raw pointers.
599#[no_mangle]
600pub unsafe extern "C" fn ket_process_metadata_json(
601    process: &mut Process,
602    buffer: *mut u8,
603    buffer_size: usize,
604    write_size: &mut usize,
605) -> i32 {
606    let metadata = process.metadata();
607    let metadata = serde_json::to_string(&metadata).unwrap();
608    let metadata = metadata.as_bytes();
609    *write_size = metadata.len();
610
611    if buffer_size >= *write_size {
612        let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
613        buffer[..*write_size].copy_from_slice(metadata);
614    }
615
616    KetError::Success.error_code()
617}
618
619/// # Safety
620#[no_mangle]
621pub unsafe extern "C" fn ket_process_set_parameter(
622    process: &mut Process,
623    param: f64,
624    index: &mut usize,
625) -> i32 {
626    match process.parameter(param) {
627        Ok(result) => {
628            *index = result;
629            KetError::Success.error_code()
630        }
631        Err(err) => err.error_code(),
632    }
633}
634
635/// # Safety
636#[no_mangle]
637pub unsafe extern "C" fn ket_process_get_gradient(
638    process: &Process,
639    index: usize,
640    available: &mut bool,
641    gradient: &mut f64,
642) -> i32 {
643    if let Some(value) = process.gradient(index) {
644        *available = true;
645        *gradient = value;
646    } else {
647        *available = false;
648    }
649    KetError::Success.error_code()
650}
651
652/// # Safety
653#[no_mangle]
654pub unsafe extern "C" fn ket_process_save_sim_state(
655    process: &Process,
656    buffer: *mut u8,
657    buffer_size: usize,
658    write_size: &mut usize,
659) -> i32 {
660    let state = process.save_sim_state();
661
662    *write_size = state.len();
663    if buffer_size >= *write_size {
664        let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
665        buffer[..*write_size].copy_from_slice(&state);
666    }
667
668    KetError::Success.error_code()
669}
670
671/// # Safety
672#[no_mangle]
673pub unsafe extern "C" fn ket_process_load_sim_state(
674    process: &mut Process,
675    data: *const u8,
676    size: usize,
677) -> i32 {
678    let data = unsafe { std::slice::from_raw_parts(data, size) };
679
680    process.load_sim_state(data);
681
682    KetError::Success.error_code()
683}
684
685/// # Safety
686#[no_mangle]
687pub unsafe extern "C" fn ket_process_is_diagonal_begin(process: &mut Process) -> i32 {
688    process.is_diagonal_begin();
689    KetError::Success.error_code()
690}
691
692/// # Safety
693#[no_mangle]
694pub unsafe extern "C" fn ket_process_is_diagonal_end(process: &mut Process) -> i32 {
695    process.is_diagonal_end();
696    KetError::Success.error_code()
697}
698
699/// # Safety
700#[no_mangle]
701pub unsafe extern "C" fn ket_process_is_permutation_begin(process: &mut Process) -> i32 {
702    process.is_permutation_begin();
703
704    KetError::Success.error_code()
705}
706
707/// # Safety
708#[no_mangle]
709pub unsafe extern "C" fn ket_process_is_permutation_end(process: &mut Process) -> i32 {
710    process.is_permutation_end();
711
712    KetError::Success.error_code()
713}
714
715/// # Safety
716#[no_mangle]
717pub unsafe extern "C" fn ket_process_around_begin(process: &mut Process) -> i32 {
718    process.around_begin();
719    KetError::Success.error_code()
720}
721
722/// # Safety
723#[no_mangle]
724pub unsafe extern "C" fn ket_process_around_mid(process: &mut Process) -> i32 {
725    process.around_mid();
726    KetError::Success.error_code()
727}
728
729/// # Safety
730#[no_mangle]
731pub unsafe extern "C" fn ket_process_around_undo(process: &mut Process) -> i32 {
732    process.around_undo();
733    KetError::Success.error_code()
734}
735
736/// # Safety
737#[no_mangle]
738pub unsafe extern "C" fn ket_process_around_end(process: &mut Process) -> i32 {
739    process.around_end();
740    KetError::Success.error_code()
741}
742
743/// # Safety
744#[no_mangle]
745pub unsafe extern "C" fn ket_process_allocate_aux(
746    process: &mut Process,
747    size: usize,
748    interacting_qubits: *const usize,
749    interacting_qubits_size: usize,
750    aux_begin: &mut usize,
751    aux_id: &mut usize,
752) -> i32 {
753    let interacting_qubits = if interacting_qubits_size == 0 {
754        None
755    } else {
756        let interacting_qubits =
757            std::slice::from_raw_parts(interacting_qubits, interacting_qubits_size);
758        Some(
759            interacting_qubits
760                .iter()
761                .cloned()
762                .map(LogicalQubit::main)
763                .collect_vec(),
764        )
765    };
766
767    match process.alloc_aux(size, interacting_qubits.as_deref()) {
768        Ok((aux, id)) => {
769            *aux_begin = aux[0].index();
770            *aux_id = id;
771            KetError::Success.error_code()
772        }
773        Err(err) => err.error_code(),
774    }
775}
776
777/// # Safety
778#[no_mangle]
779pub unsafe extern "C" fn ket_process_free_aux(process: &mut Process, aux_id: usize) -> i32 {
780    process.free_aux(aux_id);
781
782    KetError::Success.error_code()
783}
784
785/// # Safety
786#[no_mangle]
787pub unsafe extern "C" fn ket_process_approximated_decomposition_begin(
788    process: &mut Process,
789) -> i32 {
790    process.approximated_decomposition_begin();
791
792    KetError::Success.error_code()
793}
794
795/// # Safety
796#[no_mangle]
797pub unsafe extern "C" fn ket_process_approximated_decomposition_end(process: &mut Process) -> i32 {
798    process.approximated_decomposition_end();
799
800    KetError::Success.error_code()
801}