use std::ffi::CString;
use super::{
catch_quest_exception,
ffi,
BitEncoding,
ComplexMatrix2,
ComplexMatrix4,
ComplexMatrixN,
PauliHamil,
PauliOpType,
PhaseFunc,
Qcomplex,
Qreal,
QuestEnv,
QuestError,
Vector,
};
#[derive(Debug)]
pub struct Qureg<'a> {
pub(crate) env: &'a QuestEnv,
pub(crate) reg: ffi::Qureg,
}
impl<'a> Qureg<'a> {
pub fn try_new(
num_qubits: i32,
env: &'a QuestEnv,
) -> Result<Self, QuestError> {
Ok(Self {
env,
reg: catch_quest_exception(|| unsafe {
ffi::createQureg(num_qubits, env.0)
})?,
})
}
pub fn try_new_density(
num_qubits: i32,
env: &'a QuestEnv,
) -> Result<Self, QuestError> {
Ok(Self {
env,
reg: catch_quest_exception(|| unsafe {
ffi::createDensityQureg(num_qubits, env.0)
})?,
})
}
#[must_use]
pub fn is_density_matrix(&self) -> bool {
self.reg.isDensityMatrix != 0
}
pub fn report_state(&self) {
catch_quest_exception(|| unsafe { ffi::reportState(self.reg) })
.expect("report_state should never fail");
}
pub fn report_state_to_screen(
&self,
report_rank: i32,
) {
catch_quest_exception(|| unsafe {
ffi::reportStateToScreen(self.reg, self.env.0, report_rank);
})
.expect("report_state_to screen should never fail");
}
#[must_use]
pub const fn num_qubits(&self) -> i32 {
self.reg.numQubitsRepresented
}
#[must_use]
pub fn num_amps_total(&self) -> i64 {
self.reg.numAmpsTotal
}
pub fn report_qureg_params(&self) {
catch_quest_exception(|| unsafe {
ffi::reportQuregParams(self.reg);
})
.expect("report_qureg_params should never fail");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_blank_state(&mut self) {
catch_quest_exception(|| unsafe {
ffi::initBlankState(self.reg);
})
.expect("init_blank_state should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_zero_state(&mut self) {
catch_quest_exception(|| unsafe {
ffi::initZeroState(self.reg);
})
.expect("init_zero_state should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_plus_state(&mut self) {
catch_quest_exception(|| unsafe {
ffi::initPlusState(self.reg);
})
.expect("init_plus_state should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_classical_state(
&mut self,
state_ind: i64,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::initClassicalState(self.reg, state_ind);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_pure_state(
&mut self,
pure_: &Qureg<'_>,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::initPureState(self.reg, pure_.reg);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_debug_state(&mut self) {
catch_quest_exception(|| unsafe {
ffi::initDebugState(self.reg);
})
.expect("init_debug_state() should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn init_state_from_amps(
&mut self,
reals: &[Qreal],
imags: &[Qreal],
) -> Result<(), QuestError> {
let num_amps_total = self.num_amps_total() as usize;
if reals.len() < num_amps_total || imags.len() < num_amps_total {
return Err(QuestError::ArrayLengthError);
}
catch_quest_exception(|| unsafe {
ffi::initStateFromAmps(self.reg, reals.as_ptr(), imags.as_ptr());
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn set_amps(
&mut self,
start_ind: i64,
reals: &[Qreal],
imags: &[Qreal],
) -> Result<(), QuestError> {
if reals.len() != imags.len() {
return Err(QuestError::ArrayLengthError);
}
let num_amps = reals.len() as i64;
catch_quest_exception(|| unsafe {
ffi::setAmps(
self.reg,
start_ind,
reals.as_ptr(),
imags.as_ptr(),
num_amps,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn set_density_amps(
&mut self,
start_row: i64,
start_col: i64,
reals: &[Qreal],
imags: &[Qreal],
) -> Result<(), QuestError> {
if reals.len() != imags.len() {
return Err(QuestError::ArrayLengthError);
}
let num_amps = reals.len() as i64;
catch_quest_exception(|| unsafe {
ffi::setDensityAmps(
self.reg,
start_row,
start_col,
reals.as_ptr(),
imags.as_ptr(),
num_amps,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn phase_shift(
&mut self,
target_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::phaseShift(self.reg, target_qubit, angle);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_phase_shift(
&mut self,
id_qubit1: i32,
id_qubit2: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledPhaseShift(self.reg, id_qubit1, id_qubit2, angle);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_phase_shift(
&mut self,
control_qubits: &[i32],
angle: Qreal,
) -> Result<(), QuestError> {
let num_control_qubits = control_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledPhaseShift(
self.reg,
control_qubits.as_ptr(),
num_control_qubits,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_phase_flip(
&mut self,
id_qubit1: i32,
id_qubit2: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledPhaseFlip(self.reg, id_qubit1, id_qubit2);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_phase_flip(
&mut self,
control_qubits: &[i32],
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::multiControlledPhaseFlip(
self.reg,
control_qubits.as_ptr(),
control_qubits.len() as i32,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn s_gate(
&mut self,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::sGate(self.reg, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn t_gate(
&mut self,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::tGate(self.reg, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn clone_qureg(
&mut self,
copy_qureg: &Qureg<'_>,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::cloneQureg(self.reg, copy_qureg.reg);
})
}
#[must_use]
pub fn sync_quest_success(success_code: i32) -> i32 {
catch_quest_exception(|| unsafe { ffi::syncQuESTSuccess(success_code) })
.expect("sync_quest_success should always succeed")
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn copy_state_to_gpu(&mut self) {
catch_quest_exception(|| unsafe {
ffi::copyStateToGPU(self.reg);
})
.expect("copy_state_to_gpu should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn copy_state_from_gpu(&mut self) {
catch_quest_exception(|| unsafe { ffi::copyStateFromGPU(self.reg) })
.expect("copy_state_from_gpu should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn copy_substate_to_gpu(
&mut self,
start_ind: i64,
num_amps: i64,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::copySubstateToGPU(self.reg, start_ind, num_amps);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn copy_substate_from_gpu(
&mut self,
start_ind: i64,
num_amps: i64,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::copySubstateToGPU(self.reg, start_ind, num_amps);
})
}
pub fn get_amp(
&self,
index: i64,
) -> Result<Qcomplex, QuestError> {
catch_quest_exception(|| unsafe { ffi::getAmp(self.reg, index) })
.map(Into::into)
}
pub fn get_real_amp(
&self,
index: i64,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe { ffi::getRealAmp(self.reg, index) })
}
pub fn get_imag_amp(
&self,
index: i64,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe { ffi::getImagAmp(self.reg, index) })
}
pub fn get_prob_amp(
&self,
index: i64,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe { ffi::getProbAmp(self.reg, index) })
}
pub fn get_density_amp(
&self,
row: i64,
col: i64,
) -> Result<Qcomplex, QuestError> {
catch_quest_exception(|| unsafe {
ffi::getDensityAmp(self.reg, row, col)
})
.map(Into::into)
}
#[must_use]
pub fn calc_total_prob(&self) -> Qreal {
catch_quest_exception(|| unsafe { ffi::calcTotalProb(self.reg) })
.expect("calc_total_prop should always succeed")
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn compact_unitary(
&mut self,
target_qubit: i32,
alpha: Qcomplex,
beta: Qcomplex,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::compactUnitary(
self.reg,
target_qubit,
alpha.into(),
beta.into(),
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn unitary(
&mut self,
target_qubit: i32,
u: &ComplexMatrix2,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::unitary(self.reg, target_qubit, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn rotate_x(
&mut self,
rot_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::rotateX(self.reg, rot_qubit, angle);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn rotate_y(
&mut self,
rot_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::rotateY(self.reg, rot_qubit, angle);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn rotate_z(
&mut self,
rot_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::rotateZ(self.reg, rot_qubit, angle);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn rotate_around_axis(
&mut self,
rot_qubit: i32,
angle: Qreal,
axis: &Vector,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::rotateAroundAxis(self.reg, rot_qubit, angle, axis.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_rotate_x(
&mut self,
control_qubit: i32,
target_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledRotateX(
self.reg,
control_qubit,
target_qubit,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_rotate_y(
&mut self,
control_qubit: i32,
target_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledRotateY(
self.reg,
control_qubit,
target_qubit,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_rotate_z(
&mut self,
control_qubit: i32,
target_qubit: i32,
angle: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledRotateZ(
self.reg,
control_qubit,
target_qubit,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_rotate_around_axis(
&mut self,
control_qubit: i32,
target_qubit: i32,
angle: Qreal,
axis: &Vector,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledRotateAroundAxis(
self.reg,
control_qubit,
target_qubit,
angle,
axis.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_compact_unitary(
&mut self,
control_qubit: i32,
target_qubit: i32,
alpha: Qcomplex,
beta: Qcomplex,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledCompactUnitary(
self.reg,
control_qubit,
target_qubit,
alpha.into(),
beta.into(),
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_unitary(
&mut self,
control_qubit: i32,
target_qubit: i32,
u: &ComplexMatrix2,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledUnitary(self.reg, control_qubit, target_qubit, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_unitary(
&mut self,
control_qubits: &[i32],
target_qubit: i32,
u: &ComplexMatrix2,
) -> Result<(), QuestError> {
let num_control_qubits = control_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledUnitary(
self.reg,
control_qubits.as_ptr(),
num_control_qubits,
target_qubit,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn pauli_x(
&mut self,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::pauliX(self.reg, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn pauli_y(
&mut self,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::pauliY(self.reg, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn pauli_z(
&mut self,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::pauliZ(self.reg, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn hadamard(
&mut self,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::hadamard(self.reg, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_not(
&mut self,
control_qubit: i32,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledNot(self.reg, control_qubit, target_qubit);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_multi_qubit_not(
&mut self,
ctrls: &[i32],
targs: &[i32],
) -> Result<(), QuestError> {
let num_ctrls = ctrls.len() as i32;
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledMultiQubitNot(
self.reg,
ctrls.as_ptr(),
num_ctrls,
targs.as_ptr(),
num_targs,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_qubit_not(
&mut self,
targs: &[i32],
) -> Result<(), QuestError> {
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
let targs_ptr = targs.as_ptr();
ffi::multiQubitNot(self.reg, targs_ptr, num_targs);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_pauli_y(
&mut self,
control_qubit: i32,
target_qubit: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledPauliY(self.reg, control_qubit, target_qubit);
})
}
pub fn calc_prob_of_outcome(
&self,
measure_qubit: i32,
outcome: i32,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe {
ffi::calcProbOfOutcome(self.reg, measure_qubit, outcome)
})
}
#[allow(clippy::cast_sign_loss)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn calc_prob_of_all_outcomes(
&self,
outcome_probs: &mut [Qreal],
qubits: &[i32],
) -> Result<(), QuestError> {
if outcome_probs.len() < 1 << qubits.len() {
return Err(QuestError::ArrayLengthError);
}
let num_qubits = qubits.len() as i32;
let outcome_probs_ptr = outcome_probs.as_mut_ptr();
catch_quest_exception(|| unsafe {
ffi::calcProbOfAllOutcomes(
outcome_probs_ptr,
self.reg,
qubits.as_ptr(),
num_qubits,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn collapse_to_outcome(
&mut self,
measure_qubit: i32,
outcome: i32,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe {
ffi::collapseToOutcome(self.reg, measure_qubit, outcome)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn measure(
&mut self,
measure_qubit: i32,
) -> Result<i32, QuestError> {
catch_quest_exception(|| unsafe {
ffi::measure(self.reg, measure_qubit)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn measure_with_stats(
&mut self,
measure_qubit: i32,
outcome_prob: &mut Qreal,
) -> Result<i32, QuestError> {
let outcome_prob_ptr = outcome_prob as *mut _;
catch_quest_exception(|| unsafe {
ffi::measureWithStats(self.reg, measure_qubit, outcome_prob_ptr)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn start_recording_qasm(&mut self) {
catch_quest_exception(|| unsafe {
ffi::startRecordingQASM(self.reg);
})
.expect("start_recording_qasm should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn stop_recording_qasm(&mut self) {
catch_quest_exception(|| unsafe {
ffi::stopRecordingQASM(self.reg);
})
.expect("stop_recording_qasm should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn clear_recorded_qasm(&mut self) {
catch_quest_exception(|| unsafe {
ffi::clearRecordedQASM(self.reg);
})
.expect("clear_recorded_qasm should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn print_recorded_qasm(&mut self) {
catch_quest_exception(|| unsafe {
ffi::printRecordedQASM(self.reg);
})
.expect("print_recorded_qasm should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn write_recorded_qasm_to_file(
&mut self,
filename: &str,
) -> Result<(), QuestError> {
unsafe {
let filename_cstr =
CString::new(filename).map_err(QuestError::NulError)?;
catch_quest_exception(|| {
ffi::writeRecordedQASMToFile(
self.reg,
(*filename_cstr).as_ptr(),
);
})
}
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_dephasing(
&mut self,
target_qubit: i32,
prob: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixDephasing(self.reg, target_qubit, prob);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_two_qubit_dephasing(
&mut self,
qubit1: i32,
qubit2: i32,
prob: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixTwoQubitDephasing(self.reg, qubit1, qubit2, prob);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_depolarising(
&mut self,
target_qubit: i32,
prob: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixDepolarising(self.reg, target_qubit, prob);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_damping(
&mut self,
target_qubit: i32,
prob: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixDamping(self.reg, target_qubit, prob);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_two_qubit_depolarising(
&mut self,
qubit1: i32,
qubit2: i32,
prob: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixTwoQubitDepolarising(self.reg, qubit1, qubit2, prob);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_pauli(
&mut self,
target_qubit: i32,
prob_x: Qreal,
prob_y: Qreal,
prob_z: Qreal,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixPauli(self.reg, target_qubit, prob_x, prob_y, prob_z);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_density_matrix(
&mut self,
prob: Qreal,
other_qureg: &Qureg<'_>,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::mixDensityMatrix(self.reg, prob, other_qureg.reg);
})
}
pub fn calc_purity(&self) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe { ffi::calcPurity(self.reg) })
}
pub fn calc_fidelity(
&self,
pure_state: &Qureg<'_>,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe {
ffi::calcFidelity(self.reg, pure_state.reg)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn swap_gate(
&mut self,
qubit1: i32,
qubit2: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::swapGate(self.reg, qubit1, qubit2);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn sqrt_swap_gate(
&mut self,
qb1: i32,
qb2: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::sqrtSwapGate(self.reg, qb1, qb2);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_state_controlled_unitary(
&mut self,
control_qubits: &[i32],
control_state: &[i32],
target_qubit: i32,
u: &ComplexMatrix2,
) -> Result<(), QuestError> {
let num_control_qubits = control_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiStateControlledUnitary(
self.reg,
control_qubits.as_ptr(),
control_state.as_ptr(),
num_control_qubits,
target_qubit,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_rotate_z(
&mut self,
qubits: &[i32],
angle: Qreal,
) -> Result<(), QuestError> {
let num_qubits = qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiRotateZ(self.reg, qubits.as_ptr(), num_qubits, angle);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_rotate_pauli(
&mut self,
target_qubits: &[i32],
target_paulis: &[PauliOpType],
angle: Qreal,
) -> Result<(), QuestError> {
let num_targets = target_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiRotatePauli(
self.reg,
target_qubits.as_ptr(),
target_paulis.as_ptr(),
num_targets,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_multi_rotate_z(
&mut self,
control_qubits: &[i32],
target_qubits: &[i32],
angle: Qreal,
) -> Result<(), QuestError> {
let num_controls = control_qubits.len() as i32;
let num_targets = target_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledMultiRotateZ(
self.reg,
control_qubits.as_ptr(),
num_controls,
target_qubits.as_ptr(),
num_targets,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_multi_rotate_pauli(
&mut self,
control_qubits: &[i32],
target_qubits: &[i32],
target_paulis: &[PauliOpType],
angle: Qreal,
) -> Result<(), QuestError> {
let num_controls = control_qubits.len() as i32;
let num_targets = target_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledMultiRotatePauli(
self.reg,
control_qubits.as_ptr(),
num_controls,
target_qubits.as_ptr(),
target_paulis.as_ptr(),
num_targets,
angle,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn calc_expec_pauli_prod(
&self,
target_qubits: &[i32],
pauli_codes: &[PauliOpType],
workspace: &mut Qureg<'_>,
) -> Result<Qreal, QuestError> {
let num_targets = target_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::calcExpecPauliProd(
self.reg,
target_qubits.as_ptr(),
pauli_codes.as_ptr(),
num_targets,
workspace.reg,
)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn calc_expec_pauli_sum(
&self,
all_pauli_codes: &[PauliOpType],
term_coeffs: &[Qreal],
workspace: &mut Qureg<'_>,
) -> Result<Qreal, QuestError> {
let num_sum_terms = term_coeffs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::calcExpecPauliSum(
self.reg,
all_pauli_codes.as_ptr(),
term_coeffs.as_ptr(),
num_sum_terms,
workspace.reg,
)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn calc_expec_pauli_hamil(
&self,
hamil: &PauliHamil,
workspace: &mut Qureg<'_>,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe {
ffi::calcExpecPauliHamil(self.reg, hamil.0, workspace.reg)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn two_qubit_unitary(
&mut self,
target_qubit1: i32,
target_qubit2: i32,
u: &ComplexMatrix4,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::twoQubitUnitary(self.reg, target_qubit1, target_qubit2, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_two_qubit_unitary(
&mut self,
control_qubit: i32,
target_qubit1: i32,
target_qubit2: i32,
u: &ComplexMatrix4,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::controlledTwoQubitUnitary(
self.reg,
control_qubit,
target_qubit1,
target_qubit2,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_two_qubit_unitary(
&mut self,
control_qubits: &[i32],
target_qubit1: i32,
target_qubit2: i32,
u: &ComplexMatrix4,
) -> Result<(), QuestError> {
let num_control_qubits = control_qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledTwoQubitUnitary(
self.reg,
control_qubits.as_ptr(),
num_control_qubits,
target_qubit1,
target_qubit2,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_qubit_unitary(
&mut self,
targs: &[i32],
u: &ComplexMatrixN,
) -> Result<(), QuestError> {
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiQubitUnitary(self.reg, targs.as_ptr(), num_targs, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn controlled_multi_qubit_unitary(
&mut self,
ctrl: i32,
targs: &[i32],
u: &ComplexMatrixN,
) -> Result<(), QuestError> {
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::controlledMultiQubitUnitary(
self.reg,
ctrl,
targs.as_ptr(),
num_targs,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn multi_controlled_multi_qubit_unitary(
&mut self,
ctrls: &[i32],
targs: &[i32],
u: &ComplexMatrixN,
) -> Result<(), QuestError> {
let num_ctrls = ctrls.len() as i32;
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::multiControlledMultiQubitUnitary(
self.reg,
ctrls.as_ptr(),
num_ctrls,
targs.as_ptr(),
num_targs,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_kraus_map(
&mut self,
target: i32,
ops: &[&ComplexMatrix2],
) -> Result<(), QuestError> {
let num_ops = ops.len() as i32;
let ops_inner = ops.iter().map(|x| x.0).collect::<Vec<_>>();
catch_quest_exception(|| unsafe {
ffi::mixKrausMap(self.reg, target, ops_inner.as_ptr(), num_ops);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_two_qubit_kraus_map(
&mut self,
target1: i32,
target2: i32,
ops: &[&ComplexMatrix4],
) -> Result<(), QuestError> {
let num_ops = ops.len() as i32;
let ops_inner = ops.iter().map(|x| x.0).collect::<Vec<_>>();
catch_quest_exception(|| unsafe {
ffi::mixTwoQubitKrausMap(
self.reg,
target1,
target2,
ops_inner.as_ptr(),
num_ops,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_multi_qubit_kraus_map(
&mut self,
targets: &[i32],
ops: &[&ComplexMatrixN],
) -> Result<(), QuestError> {
let num_targets = targets.len() as i32;
let num_ops = ops.len() as i32;
let ops_inner = ops.iter().map(|x| x.0).collect::<Vec<_>>();
catch_quest_exception(|| unsafe {
ffi::mixMultiQubitKrausMap(
self.reg,
targets.as_ptr(),
num_targets,
ops_inner.as_ptr(),
num_ops,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_nontp_kraus_map(
&mut self,
target: i32,
ops: &[&ComplexMatrix2],
) -> Result<(), QuestError> {
let num_ops = ops.len() as i32;
let ops_inner = ops.iter().map(|x| x.0).collect::<Vec<_>>();
catch_quest_exception(|| unsafe {
ffi::mixNonTPKrausMap(
self.reg,
target,
ops_inner.as_ptr(),
num_ops,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_nontp_two_qubit_kraus_map(
&mut self,
target1: i32,
target2: i32,
ops: &[&ComplexMatrix4],
) -> Result<(), QuestError> {
let num_ops = ops.len() as i32;
let ops_inner = ops.iter().map(|x| x.0).collect::<Vec<_>>();
catch_quest_exception(|| unsafe {
ffi::mixNonTPTwoQubitKrausMap(
self.reg,
target1,
target2,
ops_inner.as_ptr(),
num_ops,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn mix_nontp_multi_qubit_kraus_map(
&mut self,
targets: &[i32],
ops: &[&ComplexMatrixN],
) -> Result<(), QuestError> {
let num_targets = targets.len() as i32;
let num_ops = ops.len() as i32;
let ops_inner = ops.iter().map(|x| x.0).collect::<Vec<_>>();
catch_quest_exception(|| unsafe {
ffi::mixNonTPMultiQubitKrausMap(
self.reg,
targets.as_ptr(),
num_targets,
ops_inner.as_ptr(),
num_ops,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_trotter_circuit(
&mut self,
hamil: &PauliHamil,
time: Qreal,
order: i32,
reps: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::applyTrotterCircuit(self.reg, hamil.0, time, order, reps);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_matrix2(
&mut self,
target_qubit: i32,
u: &ComplexMatrix2,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::applyMatrix2(self.reg, target_qubit, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_matrix4(
&mut self,
target_qubit1: i32,
target_qubit2: i32,
u: &ComplexMatrix4,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::applyMatrix4(self.reg, target_qubit1, target_qubit2, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_matrix_n(
&mut self,
targs: &[i32],
u: &ComplexMatrixN,
) -> Result<(), QuestError> {
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyMatrixN(self.reg, targs.as_ptr(), num_targs, u.0);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_multi_controlled_matrix_n(
&mut self,
ctrls: &[i32],
targs: &[i32],
u: &ComplexMatrixN,
) -> Result<(), QuestError> {
let num_ctrls = ctrls.len() as i32;
let num_targs = targs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyMultiControlledMatrixN(
self.reg,
ctrls.as_ptr(),
num_ctrls,
targs.as_ptr(),
num_targs,
u.0,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_phase_func(
&mut self,
qubits: &[i32],
encoding: BitEncoding,
coeffs: &[Qreal],
exponents: &[Qreal],
) -> Result<(), QuestError> {
let num_qubits = qubits.len() as i32;
let num_terms = coeffs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyPhaseFunc(
self.reg,
qubits.as_ptr(),
num_qubits,
encoding,
coeffs.as_ptr(),
exponents.as_ptr(),
num_terms,
);
})
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_phase_func_overrides(
&mut self,
qubits: &[i32],
encoding: BitEncoding,
coeffs: &[Qreal],
exponents: &[Qreal],
override_inds: &[i64],
override_phases: &[Qreal],
) -> Result<(), QuestError> {
let num_qubits = qubits.len() as i32;
let num_terms = coeffs.len() as i32;
let num_overrides = override_inds.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyPhaseFuncOverrides(
self.reg,
qubits.as_ptr(),
num_qubits,
encoding,
coeffs.as_ptr(),
exponents.as_ptr(),
num_terms,
override_inds.as_ptr(),
override_phases.as_ptr(),
num_overrides,
);
})
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_multi_var_phase_func(
&mut self,
qubits: &[i32],
num_qubits_per_reg: &[i32],
encoding: BitEncoding,
coeffs: &[Qreal],
exponents: &[Qreal],
num_terms_per_reg: &[i32],
) -> Result<(), QuestError> {
let num_regs = num_qubits_per_reg.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyMultiVarPhaseFunc(
self.reg,
qubits.as_ptr(),
num_qubits_per_reg.as_ptr(),
num_regs,
encoding,
coeffs.as_ptr(),
exponents.as_ptr(),
num_terms_per_reg.as_ptr(),
);
})
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_multi_var_phase_func_overrides(
&mut self,
qubits: &[i32],
num_qubits_per_reg: &[i32],
encoding: BitEncoding,
coeffs: &[Qreal],
exponents: &[Qreal],
num_terms_per_reg: &[i32],
override_inds: &[i64],
override_phases: &[Qreal],
) -> Result<(), QuestError> {
let num_regs = num_qubits_per_reg.len() as i32;
let num_overrides = override_phases.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyMultiVarPhaseFuncOverrides(
self.reg,
qubits.as_ptr(),
num_qubits_per_reg.as_ptr(),
num_regs,
encoding,
coeffs.as_ptr(),
exponents.as_ptr(),
num_terms_per_reg.as_ptr(),
override_inds.as_ptr(),
override_phases.as_ptr(),
num_overrides,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_named_phase_func(
&mut self,
qubits: &[i32],
num_qubits_per_reg: &[i32],
encoding: BitEncoding,
function_name_code: PhaseFunc,
) -> Result<(), QuestError> {
let num_regs = num_qubits_per_reg.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyNamedPhaseFunc(
self.reg,
qubits.as_ptr(),
num_qubits_per_reg.as_ptr(),
num_regs,
encoding,
function_name_code,
);
})
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_named_phase_func_overrides(
&mut self,
qubits: &[i32],
num_qubits_per_reg: &[i32],
encoding: BitEncoding,
function_name_code: PhaseFunc,
override_inds: &[i64],
override_phases: &[Qreal],
) -> Result<(), QuestError> {
let num_regs = num_qubits_per_reg.len() as i32;
let num_overrides = override_phases.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyNamedPhaseFuncOverrides(
self.reg,
qubits.as_ptr(),
num_qubits_per_reg.as_ptr(),
num_regs,
encoding,
function_name_code,
override_inds.as_ptr(),
override_phases.as_ptr(),
num_overrides,
);
})
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_param_named_phase_func(
&mut self,
qubits: &[i32],
num_qubits_per_reg: &[i32],
encoding: BitEncoding,
function_name_code: PhaseFunc,
params: &[Qreal],
) -> Result<(), QuestError> {
let num_regs = num_qubits_per_reg.len() as i32;
let num_params = params.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyParamNamedPhaseFunc(
self.reg,
qubits.as_ptr(),
num_qubits_per_reg.as_ptr(),
num_regs,
encoding,
function_name_code,
params.as_ptr(),
num_params,
);
})
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_param_named_phase_func_overrides(
&mut self,
qubits: &[i32],
num_qubits_per_reg: &[i32],
encoding: BitEncoding,
function_name_code: PhaseFunc,
params: &[Qreal],
override_inds: &[i64],
override_phases: &[Qreal],
) -> Result<(), QuestError> {
let num_regs = num_qubits_per_reg.len() as i32;
let num_params = params.len() as i32;
let num_overrides = override_phases.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyParamNamedPhaseFuncOverrides(
self.reg,
qubits.as_ptr(),
num_qubits_per_reg.as_ptr(),
num_regs,
encoding,
function_name_code,
params.as_ptr(),
num_params,
override_inds.as_ptr(),
override_phases.as_ptr(),
num_overrides,
);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_full_qft(&mut self) {
catch_quest_exception(|| unsafe {
ffi::applyFullQFT(self.reg);
})
.expect("apply_full_qft should always succeed");
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_qft(
&mut self,
qubits: &[i32],
) -> Result<(), QuestError> {
let num_qubits = qubits.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyQFT(self.reg, qubits.as_ptr(), num_qubits);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_projector(
&mut self,
qubit: i32,
outcome: i32,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::applyProjector(self.reg, qubit, outcome);
})
}
}
impl<'a> Drop for Qureg<'a> {
fn drop(&mut self) {
catch_quest_exception(|| {
unsafe { ffi::destroyQureg(self.reg, self.env.0) };
})
.expect("dropping Qureg should always succeed");
}
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_pauli_hamil(
in_qureg: &mut Qureg<'_>,
hamil: &PauliHamil,
out_qureg: &mut Qureg<'_>,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::applyPauliHamil(in_qureg.reg, hamil.0, out_qureg.reg);
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn apply_pauli_sum(
in_qureg: &mut Qureg<'_>,
all_pauli_codes: &[PauliOpType],
term_coeffs: &[Qreal],
out_qureg: &mut Qureg<'_>,
) -> Result<(), QuestError> {
let num_sum_terms = term_coeffs.len() as i32;
catch_quest_exception(|| unsafe {
ffi::applyPauliSum(
in_qureg.reg,
all_pauli_codes.as_ptr(),
term_coeffs.as_ptr(),
num_sum_terms,
out_qureg.reg,
);
})
}
pub fn calc_hilbert_schmidt_distance(
a: &Qureg<'_>,
b: &Qureg<'_>,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe {
ffi::calcHilbertSchmidtDistance(a.reg, b.reg)
})
}
pub fn calc_inner_product(
bra: &Qureg<'_>,
ket: &Qureg<'_>,
) -> Result<Qcomplex, QuestError> {
catch_quest_exception(|| unsafe { ffi::calcInnerProduct(bra.reg, ket.reg) })
.map(Into::into)
}
pub fn calc_density_inner_product(
rho1: &Qureg<'_>,
rho2: &Qureg<'_>,
) -> Result<Qreal, QuestError> {
catch_quest_exception(|| unsafe {
ffi::calcDensityInnerProduct(rho1.reg, rho2.reg)
})
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub fn set_weighted_qureg(
fac1: Qcomplex,
qureg1: &Qureg<'_>,
fac2: Qcomplex,
qureg2: &Qureg<'_>,
fac_out: Qcomplex,
out: &mut Qureg<'_>,
) -> Result<(), QuestError> {
catch_quest_exception(|| unsafe {
ffi::setWeightedQureg(
fac1.into(),
qureg1.reg,
fac2.into(),
qureg2.reg,
fac_out.into(),
out.reg,
);
})
}