use num::Integer;
use serde::Serialize;
use x::CXMode;
pub(crate) mod network;
pub(crate) mod su2;
pub(crate) mod u2;
pub(crate) mod util;
pub(crate) mod x;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Hash)]
pub enum AuxMode {
Clean,
Dirty,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Hash)]
pub enum DepthMode {
Log,
Linear,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Default, Hash)]
pub(crate) enum Algorithm {
VChain(CXMode, AuxMode),
NetworkU2(CXMode),
NetworkPauli(CXMode),
#[default]
LinearDepth,
}
impl std::fmt::Display for Algorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
fn num_aux_network_u2(cx_mode: CXMode, n: usize) -> usize {
let n_cx = match cx_mode {
CXMode::C2X => 2,
CXMode::C3X => 3,
};
let (a, rem) = n.div_rem(&n_cx);
if n == 1 {
0
} else if n == 2 && matches!(cx_mode, CXMode::C3X) {
1
} else {
a + num_aux_network_u2(cx_mode, a + rem)
}
}
fn num_aux_network_pauli(cx_mode: CXMode, n: usize) -> usize {
let n_cx = match cx_mode {
CXMode::C2X => 2,
CXMode::C3X => 3,
};
let (a, rem) = n.div_rem(&n_cx);
if n <= n_cx {
0
} else {
a + num_aux_network_pauli(cx_mode, a + rem)
}
}
impl Algorithm {
pub fn aux_needed(self, n: usize) -> usize {
match self {
Self::VChain(cx_mode, _) => match cx_mode {
CXMode::C2X => n - 2,
CXMode::C3X => usize::div_ceil(n - 3, 2),
},
Self::NetworkU2(cx_mode) => num_aux_network_u2(cx_mode, n),
Self::NetworkPauli(cx_mode) => num_aux_network_pauli(cx_mode, n),
Self::LinearDepth => 0,
}
}
}