1use 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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[no_mangle]
423pub extern "C" fn ket_process_ctrl_pop(process: &mut Process) -> i32 {
424 wrapper(process.ctrl_pop())
425}
426
427#[no_mangle]
441pub unsafe extern "C" fn ket_process_ctrl_stack(process: &mut Process) -> i32 {
442 wrapper(process.ctrl_begin())
443}
444
445#[no_mangle]
455pub extern "C" fn ket_process_ctrl_unstack(process: &mut Process) -> i32 {
456 wrapper(process.ctrl_end())
457}
458
459#[no_mangle]
469pub extern "C" fn ket_process_adj_begin(process: &mut Process) -> i32 {
470 wrapper(process.adj_begin())
471}
472
473#[no_mangle]
483pub extern "C" fn ket_process_adj_end(process: &mut Process) -> i32 {
484 wrapper(process.adj_end())
485}
486
487#[no_mangle]
497pub extern "C" fn ket_process_execute(process: &mut Process) -> i32 {
498 wrapper(process.execute())
499}
500
501#[no_mangle]
511pub extern "C" fn ket_process_prepare_for_execution(process: &mut Process) -> i32 {
512 wrapper(process.prepare_for_execution())
513}
514
515#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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#[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}