1use itertools::Itertools;
7
8use crate::{
9 execution::*,
10 ir::{
11 instructions::Instruction,
12 qubit::{LogicalQubit, Qubit},
13 },
14 prelude::{Hamiltonian, QuantumGate},
15 process::{DumpData, Sample},
16};
17
18#[repr(C)]
19#[derive(Debug, Clone)]
20pub struct BatchCExecution {
21 submit_execution: fn(*const u8, usize, *const f64, usize),
22 get_results: fn(data: &mut *const u8, len: &mut usize),
23 clear: fn(),
24}
25
26impl BatchExecution for BatchCExecution {
27 fn submit_execution(&mut self, circuit: &[Instruction<usize>], parameters: &[f64]) {
28 let circuit = serde_json::to_vec(circuit).unwrap();
29 (self.submit_execution)(
30 circuit.as_ptr(),
31 circuit.len(),
32 parameters.as_ptr(),
33 parameters.len(),
34 );
35 }
36
37 fn get_results(&mut self) -> ResultData {
38 let mut buffer = std::ptr::null();
39 let mut len: usize = 0;
40 (self.get_results)(&mut buffer, &mut len);
41 let buffer = unsafe { std::slice::from_raw_parts(buffer, len) };
42 serde_json::from_slice(buffer).unwrap()
43 }
44
45 fn clear(&mut self) {
46 (self.clear)();
47 }
48}
49
50#[repr(C)]
51#[derive(Debug, Clone)]
52pub struct LiveCExecution {
53 gate: fn(*const u8, usize, usize, *const usize, usize),
54 measure: fn(*const usize, usize) -> u64,
55 exp_value: fn(*const u8, usize) -> f64,
56 sample: fn(*const usize, usize, usize, &mut *const u8, &mut usize),
57 dump: fn(*const usize, usize, &mut *const u8, &mut usize),
58 save: fn(&mut *const u8, &mut usize),
59 load: fn(*const u8, usize),
60}
61
62impl LiveExecution for LiveCExecution {
63 fn gate(&mut self, gate: QuantumGate, target: LogicalQubit, control: &[LogicalQubit]) {
64 assert!(target.is_main());
65 assert!(!control.iter().any(Qubit::is_aux));
66 let gate = serde_json::to_vec(&gate).unwrap();
67 let control = control.iter().map(Qubit::index).collect_vec();
68 (self.gate)(
69 gate.as_ptr(),
70 gate.len(),
71 target.index(),
72 control.as_ptr(),
73 control.len(),
74 );
75 }
76
77 fn measure(&mut self, qubits: &[LogicalQubit]) -> u64 {
78 assert!(!qubits.iter().any(Qubit::is_aux));
79 let qubits = qubits.iter().map(Qubit::index).collect_vec();
80
81 (self.measure)(qubits.as_ptr(), qubits.len())
82 }
83
84 fn exp_value(&mut self, hamiltonian: &Hamiltonian<LogicalQubit>) -> f64 {
85 let hamiltonian = serde_json::to_vec(&hamiltonian.to_usize_qubit()).unwrap();
86
87 (self.exp_value)(hamiltonian.as_ptr(), hamiltonian.len())
88 }
89
90 fn sample(&mut self, qubits: &[LogicalQubit], shots: usize) -> Sample {
91 assert!(!qubits.iter().any(Qubit::is_aux));
92 let qubits = qubits.iter().map(Qubit::index).collect_vec();
93
94 let mut result = std::ptr::null();
95 let mut size = 0;
96 (self.sample)(qubits.as_ptr(), qubits.len(), shots, &mut result, &mut size);
97
98 serde_json::from_slice(unsafe { std::slice::from_raw_parts(result, size) }).unwrap()
99 }
100
101 fn dump(&mut self, qubits: &[LogicalQubit]) -> DumpData {
102 assert!(!qubits.iter().any(Qubit::is_aux));
103 let qubits = qubits.iter().map(Qubit::index).collect_vec();
104
105 let mut result = std::ptr::null();
106 let mut size = 0;
107 (self.dump)(qubits.as_ptr(), qubits.len(), &mut result, &mut size);
108
109 serde_json::from_slice(unsafe { std::slice::from_raw_parts(result, size) }).unwrap()
110 }
111
112 fn save(&self) -> Vec<u8> {
113 let mut result = std::ptr::null();
114 let mut size = 0;
115 (self.save)(&mut result, &mut size);
116
117 unsafe { std::slice::from_raw_parts(result, size).to_vec() }
118 }
119
120 fn load(&mut self, data: &[u8]) {
121 (self.load)(data.as_ptr(), data.len())
122 }
123}
124
125#[no_mangle]
126pub unsafe extern "C" fn ket_make_configuration(
128 execution_target_json: *const u8,
129 execution_target_size: usize,
130 batch_execution: *const BatchCExecution,
131 live_execution: *const LiveCExecution,
132 result: &mut *mut (ExecutionTarget, Option<QuantumExecution>),
133) -> i32 {
134 let execution: Option<QuantumExecution> = if !batch_execution.is_null() {
135 Some(QuantumExecution::Batch(Box::new(unsafe {
136 (*batch_execution).clone()
137 })))
138 } else if !live_execution.is_null() {
139 Some(QuantumExecution::Live(Box::new(unsafe {
140 (*live_execution).clone()
141 })))
142 } else {
143 None
144 };
145
146 let execution_target =
147 unsafe { std::slice::from_raw_parts(execution_target_json, execution_target_size) };
148 let execution_target = serde_json::from_slice(execution_target).unwrap();
149
150 *result = Box::into_raw(Box::new((execution_target, execution)));
151
152 0
153}