use super::*;
use crate::common::gates::UnitaryGateType;
use std::convert::TryFrom;
fn new_predef_helper(
gate_type: dqcs_predefined_gate_t,
qubits: Vec<QubitRef>,
param_data: dqcs_handle_t,
) -> Result<dqcs_handle_t> {
let gate_type = UnitaryGateType::try_from(gate_type)?;
resolve!(optional param_data as pending ArbData);
let data: ArbData = {
if let Some(data) = param_data.as_ref() {
let x: &ArbData = data.as_ref().unwrap();
x.clone()
} else {
ArbData::default()
}
};
let gate = insert(
gate_type
.into_gate_converter(None, 0., false)
.construct(&(qubits, data))?,
);
if let Some(mut param_data) = param_data {
delete!(resolved param_data);
}
Ok(gate)
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_predef(
gate_type: dqcs_predefined_gate_t,
qubits: dqcs_handle_t,
param_data: dqcs_handle_t,
) -> dqcs_handle_t {
api_return(0, || {
resolve!(qubits as pending QubitReferenceSet);
let qubit_vec: Vec<QubitRef> = {
let x: &QubitReferenceSet = qubits.as_ref().unwrap();
x.iter().cloned().collect()
};
let gate = new_predef_helper(gate_type, qubit_vec, param_data)?;
delete!(resolved qubits);
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_predef_one(
gate_type: dqcs_predefined_gate_t,
qa: dqcs_qubit_t,
param_data: dqcs_handle_t,
) -> dqcs_handle_t {
api_return(0, || {
let qubits_vec = vec![QubitRef::from_foreign(qa)
.ok_or_else(oe_inv_arg("0 is not a valid qubit reference"))?];
new_predef_helper(gate_type, qubits_vec, param_data)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_predef_two(
gate_type: dqcs_predefined_gate_t,
qa: dqcs_qubit_t,
qb: dqcs_qubit_t,
param_data: dqcs_handle_t,
) -> dqcs_handle_t {
api_return(0, || {
let qubits_vec = vec![
QubitRef::from_foreign(qa)
.ok_or_else(oe_inv_arg("0 is not a valid qubit reference"))?,
QubitRef::from_foreign(qb)
.ok_or_else(oe_inv_arg("0 is not a valid qubit reference"))?,
];
if qa == qb {
inv_arg(format!("cannot use qubit {} twice", qa))?;
}
new_predef_helper(gate_type, qubits_vec, param_data)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_predef_three(
gate_type: dqcs_predefined_gate_t,
qa: dqcs_qubit_t,
qb: dqcs_qubit_t,
qc: dqcs_qubit_t,
param_data: dqcs_handle_t,
) -> dqcs_handle_t {
api_return(0, || {
let qubits_vec = vec![
QubitRef::from_foreign(qa)
.ok_or_else(oe_inv_arg("0 is not a valid qubit reference"))?,
QubitRef::from_foreign(qb)
.ok_or_else(oe_inv_arg("0 is not a valid qubit reference"))?,
QubitRef::from_foreign(qc)
.ok_or_else(oe_inv_arg("0 is not a valid qubit reference"))?,
];
if qa == qb || qa == qc {
inv_arg(format!("cannot use qubit {} twice", qa))?;
}
if qb == qc {
inv_arg(format!("cannot use qubit {} twice", qb))?;
}
new_predef_helper(gate_type, qubits_vec, param_data)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_unitary(
targets: dqcs_handle_t,
controls: dqcs_handle_t,
matrix: dqcs_handle_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![]
}
};
resolve!(matrix as pending Matrix);
let matrix_ref: &Matrix = matrix.as_ref().unwrap();
let gate = insert(Gate::new_unitary(
target_vec,
control_vec,
matrix_ref.clone(),
)?);
delete!(resolved targets);
if let Some(mut controls) = controls {
delete!(resolved controls);
}
delete!(resolved matrix);
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_measurement(
measures: dqcs_handle_t,
matrix: 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()
};
resolve!(optional matrix as pending Matrix);
let defaulted_matrix = {
if let Some(matrix) = matrix.as_ref() {
let matrix: &Matrix = matrix.as_ref().unwrap();
matrix.clone()
} else {
Matrix::new_identity(2)
}
};
let gate = insert(Gate::new_measurement(measure_vec, defaulted_matrix)?);
delete!(resolved measures);
if let Some(mut matrix) = matrix {
delete!(resolved matrix);
}
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_new_prep(
targets: dqcs_handle_t,
matrix: dqcs_handle_t,
) -> dqcs_handle_t {
api_return(0, || {
resolve!(targets as pending QubitReferenceSet);
let targets_vec: Vec<QubitRef> = {
let x: &QubitReferenceSet = targets.as_ref().unwrap();
x.iter().cloned().collect()
};
resolve!(optional matrix as pending Matrix);
let defaulted_matrix = {
if let Some(matrix) = matrix.as_ref() {
let matrix: &Matrix = matrix.as_ref().unwrap();
matrix.clone()
} else {
Matrix::new_identity(2)
}
};
let gate = insert(Gate::new_prep(targets_vec, defaulted_matrix)?);
delete!(resolved targets);
if let Some(mut matrix) = matrix {
delete!(resolved matrix);
}
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: dqcs_handle_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![]
}
};
resolve!(optional matrix as pending Matrix);
let matrix_clone: Option<Matrix> = {
if let Some(matrix) = matrix.as_ref() {
let x: &Matrix = matrix.as_ref().unwrap();
Some(x.clone())
} else {
None
}
};
let gate = insert(Gate::new_custom(
name,
target_vec,
control_vec,
measure_vec,
matrix_clone,
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);
}
if let Some(mut matrix) = matrix {
delete!(resolved matrix);
}
Ok(gate)
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_type(gate: dqcs_handle_t) -> dqcs_gate_type_t {
api_return(dqcs_gate_type_t::DQCS_GATE_TYPE_INVALID, || {
resolve!(gate as &Gate);
Ok(gate.get_type().into())
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_has_name(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) -> dqcs_handle_t {
api_return(0, || {
resolve!(gate as &Gate);
Ok(insert(
gate.get_matrix()
.ok_or_else(oe_inv_arg("no matrix associated with gate"))?
.clone(),
))
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_reduce_control(
gate: dqcs_handle_t,
epsilon: c_double,
ignore_gphase: bool,
) -> dqcs_handle_t {
api_return(0, || {
resolve!(gate as &Gate);
if gate.get_matrix().is_none() {
inv_arg("no matrix associated with gate")
} else {
Ok(insert(gate.with_gate_controls(epsilon, ignore_gphase)))
}
})
}
#[no_mangle]
pub extern "C" fn dqcs_gate_expand_control(gate: dqcs_handle_t) -> dqcs_handle_t {
api_return(0, || {
resolve!(gate as &Gate);
if gate.get_matrix().is_none() {
inv_arg("no matrix associated with gate")
} else {
Ok(insert(gate.with_matrix_controls()))
}
})
}