use super::*;
use std::mem::size_of;
use std::ptr::null_mut;
#[no_mangle]
pub extern "C" fn dqcs_gate_new_unitary(
targets: dqcs_handle_t,
controls: dqcs_handle_t,
matrix: *const c_double,
matrix_len: size_t,
) -> dqcs_handle_t {
api_return(0, || {
resolve!(targets as pending QubitReferenceSet);
let target_vec: Vec<QubitRef> = {
let x: &QubitReferenceSet = targets.as_ref().unwrap();
x.iter().cloned().collect()
};
resolve!(optional controls as pending QubitReferenceSet);
let control_vec: Vec<QubitRef> = {
if let Some(controls) = controls.as_ref() {
let x: &QubitReferenceSet = controls.as_ref().unwrap();
x.iter().cloned().collect()
} else {
vec![]
}
};
let matrix = receive_matrix(matrix, matrix_len, target_vec.len())?
.ok_or_else(oe_inv_arg("the unitary matrix cannot be null"))?;
let gate = insert(Gate::new_unitary(target_vec, control_vec, matrix)?);
delete!(resolved targets);
if let Some(mut controls) = controls {
delete!(resolved controls);
}
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_measurement(measures: dqcs_handle_t) -> dqcs_handle_t {
api_return(0, || {
resolve!(measures as pending QubitReferenceSet);
let measure_vec: Vec<QubitRef> = {
let x: &QubitReferenceSet = measures.as_ref().unwrap();
x.iter().cloned().collect()
};
let gate = insert(Gate::new_measurement(measure_vec)?);
delete!(resolved measures);
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_custom(
name: *const c_char,
targets: dqcs_handle_t,
controls: dqcs_handle_t,
measures: dqcs_handle_t,
matrix: *const c_double,
matrix_len: size_t,
) -> dqcs_handle_t {
api_return(0, || {
let name = receive_str(name)?;
resolve!(optional targets as pending QubitReferenceSet);
let target_vec: Vec<QubitRef> = {
if let Some(targets) = targets.as_ref() {
let x: &QubitReferenceSet = targets.as_ref().unwrap();
x.iter().cloned().collect()
} else {
vec![]
}
};
resolve!(optional controls as pending QubitReferenceSet);
let control_vec: Vec<QubitRef> = {
if let Some(controls) = controls.as_ref() {
let x: &QubitReferenceSet = controls.as_ref().unwrap();
x.iter().cloned().collect()
} else {
vec![]
}
};
resolve!(optional measures as pending QubitReferenceSet);
let measure_vec: Vec<QubitRef> = {
if let Some(measures) = measures.as_ref() {
let x: &QubitReferenceSet = measures.as_ref().unwrap();
x.iter().cloned().collect()
} else {
vec![]
}
};
let matrix = receive_matrix(matrix, matrix_len, target_vec.len())?;
let gate = insert(Gate::new_custom(
name,
target_vec,
control_vec,
measure_vec,
matrix,
ArbData::default(),
)?);
if let Some(mut targets) = targets {
delete!(resolved targets);
}
if let Some(mut controls) = controls {
delete!(resolved controls);
}
if let Some(mut measures) = measures {
delete!(resolved measures);
}
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_is_custom(gate: dqcs_handle_t) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(gate as &Gate);
Ok(gate.get_name().is_some())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_name(gate: dqcs_handle_t) -> *mut c_char {
api_return_string(|| {
resolve!(gate as &Gate);
Ok(gate
.get_name()
.ok_or_else(oe_inv_arg(
"gate is not custom and thus does not have a name",
))?
.to_string())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_has_targets(gate: dqcs_handle_t) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(gate as &Gate);
Ok(!gate.get_targets().is_empty())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_targets(gate: dqcs_handle_t) -> dqcs_handle_t {
api_return(0, || {
resolve!(gate as &Gate);
let targets = gate.get_targets();
let targets: QubitReferenceSet = targets.iter().cloned().collect();
Ok(insert(targets))
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_has_controls(gate: dqcs_handle_t) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(gate as &Gate);
Ok(!gate.get_controls().is_empty())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_controls(gate: dqcs_handle_t) -> dqcs_handle_t {
api_return(0, || {
resolve!(gate as &Gate);
let controls = gate.get_controls();
let controls: QubitReferenceSet = controls.iter().cloned().collect();
Ok(insert(controls))
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_has_measures(gate: dqcs_handle_t) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(gate as &Gate);
Ok(!gate.get_measures().is_empty())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_measures(gate: dqcs_handle_t) -> dqcs_handle_t {
api_return(0, || {
resolve!(gate as &Gate);
let measures = gate.get_measures();
let measures: QubitReferenceSet = measures.iter().cloned().collect();
Ok(insert(measures))
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_has_matrix(gate: dqcs_handle_t) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(gate as &Gate);
Ok(gate.get_matrix().is_some())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_matrix(gate: dqcs_handle_t) -> *mut c_double {
api_return(null_mut(), || {
resolve!(gate as &Gate);
let matrix = gate.get_matrix();
if let Some(matrix) = matrix {
let ffi_matrix =
unsafe { calloc(2 * matrix.len(), size_of::<c_double>()) as *mut c_double };
if ffi_matrix.is_null() {
err("failed to allocate return value")
} else {
for (i, x) in matrix.into_iter().enumerate() {
unsafe {
*ffi_matrix.add(i * 2) = x.re;
*ffi_matrix.add(i * 2 + 1) = x.im;
}
}
Ok(ffi_matrix)
}
} else {
inv_arg("no matrix associated with gate")
}
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_matrix_len(gate: dqcs_handle_t) -> ssize_t {
api_return(-1, || {
resolve!(gate as &Gate);
let matrix = gate.get_matrix();
if let Some(matrix) = matrix {
Ok(matrix.len() as ssize_t)
} else {
Ok(0)
}
})
}