use super::*;
use crate::common::gates::UnitaryGateType;
use std::convert::{TryFrom, TryInto};
use std::mem::size_of;
use std::ptr::null_mut;
#[no_mangle]
pub extern "C" fn dqcs_mat_new(num_qubits: size_t, matrix: *const c_double) -> dqcs_handle_t {
api_return(0, || {
if num_qubits == 0 {
inv_arg("cannot construct matrix for 0 qubits")
} else {
let num_entries = 4usize.pow(num_qubits as u32);
let mut vec = Vec::with_capacity(num_entries);
for i in 0..num_entries {
let re: f64 = unsafe { *matrix.add(i * 2) };
let im: f64 = unsafe { *matrix.add(i * 2 + 1) };
vec.push(Complex64::new(re, im));
}
Ok(insert(Matrix::new(vec)?))
}
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_predef(
gate_type: dqcs_predefined_gate_t,
param_data: dqcs_handle_t,
) -> dqcs_handle_t {
api_return(0, || {
let converter: Box<dyn MatrixConverterArb> = UnitaryGateType::try_from(gate_type)?.into();
resolve!(optional param_data as pending ArbData);
let mut data: ArbData = {
if let Some(data) = param_data.as_ref() {
let x: &ArbData = data.as_ref().unwrap();
x.clone()
} else {
ArbData::default()
}
};
let matrix = insert(converter.construct_matrix_arb(&mut data)?);
if let Some(mut param_data) = param_data {
delete!(resolved param_data);
}
Ok(matrix)
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_basis(basis: dqcs_basis_t) -> dqcs_handle_t {
api_return(0, || {
let matrix: Matrix = Basis::try_from(basis)?.into();
Ok(insert(matrix))
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_len(mat: dqcs_handle_t) -> ssize_t {
api_return(-1, || {
resolve!(mat as &Matrix);
Ok(mat.len().try_into().unwrap())
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_dimension(mat: dqcs_handle_t) -> ssize_t {
api_return(-1, || {
resolve!(mat as &Matrix);
Ok(mat.dimension().try_into().unwrap())
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_num_qubits(mat: dqcs_handle_t) -> ssize_t {
api_return(-1, || {
resolve!(mat as &Matrix);
let num_qubits = mat
.num_qubits()
.ok_or_else(oe_inv_arg("corrupted internal matrix size"))?;
Ok(num_qubits.try_into().unwrap())
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_get(mat: dqcs_handle_t) -> *mut c_double {
api_return(null_mut(), || {
resolve!(mat as &Matrix);
let ffi_matrix = unsafe { calloc(2 * mat.len(), size_of::<c_double>()) as *mut c_double };
if ffi_matrix.is_null() {
err("failed to allocate return value")
} else {
unsafe {
memcpy(
ffi_matrix as *mut c_void,
mat.as_ptr() as *const c_void,
2 * mat.len() * size_of::<c_double>(),
)
};
Ok(ffi_matrix)
}
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_approx_eq(
a: dqcs_handle_t,
b: dqcs_handle_t,
epsilon: c_double,
ignore_gphase: bool,
) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(a as &Matrix);
resolve!(b as &Matrix);
Ok(a.approx_eq(b, epsilon, ignore_gphase))
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_basis_approx_eq(
a: dqcs_handle_t,
b: dqcs_handle_t,
epsilon: c_double,
) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(a as &Matrix);
resolve!(b as &Matrix);
Ok(a.basis_approx_eq(b, epsilon))
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_approx_unitary(
matrix: dqcs_handle_t,
epsilon: c_double,
) -> dqcs_bool_return_t {
api_return_bool(|| {
resolve!(matrix as &Matrix);
Ok(matrix.approx_unitary(epsilon))
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_is_predef(
mat: dqcs_handle_t,
gate_type: dqcs_predefined_gate_t,
param_data: *mut dqcs_handle_t,
epsilon: c_double,
ignore_gphase: bool,
) -> dqcs_bool_return_t {
api_return_bool(|| {
if !param_data.is_null() {
unsafe { *param_data = 0 };
}
resolve!(mat as &Matrix);
let converter: Box<dyn MatrixConverterArb> = UnitaryGateType::try_from(gate_type)?.into();
let mut data = ArbData::default();
let result = converter.detect_matrix_arb(mat, epsilon, ignore_gphase, &mut data)?;
if !param_data.is_null() {
let handle = insert(data);
unsafe { *param_data = handle };
}
Ok(result)
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_add_controls(
mat: dqcs_handle_t,
number_of_controls: size_t,
) -> dqcs_handle_t {
api_return(0, || {
resolve!(mat as &Matrix);
Ok(insert(mat.add_controls(number_of_controls)))
})
}
#[no_mangle]
pub extern "C" fn dqcs_mat_strip_control(
mat: dqcs_handle_t,
epsilon: c_double,
ignore_global_phase: bool,
control_indices: *mut *mut ssize_t,
) -> dqcs_handle_t {
api_return(0, || {
resolve!(mat as &Matrix);
if control_indices.is_null() {
err("control_indices cannot be null")
} else {
let (control_index_hashset, submatrix) =
mat.strip_control(epsilon, ignore_global_phase);
let mut control_index_vec: Vec<usize> = control_index_hashset.into_iter().collect();
control_index_vec.sort_unstable();
let control_index_ffi = unsafe {
calloc(control_index_vec.len() + 1, size_of::<ssize_t>()) as *mut ssize_t
};
if control_index_ffi.is_null() {
err("failed to allocate control indices")
} else {
unsafe {
memcpy(
control_index_ffi as *mut c_void,
control_index_vec.as_ptr() as *const c_void,
control_index_vec.len() * size_of::<ssize_t>(),
);
*control_index_ffi.add(control_index_vec.len()) = -1;
*control_indices = control_index_ffi;
}
Ok(insert(submatrix))
}
}
})
}