use crate::traits::PauliWordTrait;
pub trait Clifford {
fn x(&mut self, addr0: usize);
fn y(&mut self, addr0: usize);
fn z(&mut self, addr0: usize);
fn h(&mut self, addr0: usize);
fn s(&mut self, addr0: usize);
fn cnot(&mut self, control: usize, target: usize);
fn cz(&mut self, addr0: usize, addr1: usize);
fn cx(&mut self, control: usize, target: usize) {
self.cnot(control, target)
}
fn zcx(&mut self, control: usize, target: usize) {
self.cnot(control, target)
}
fn zcz(&mut self, addr0: usize, addr1: usize) {
self.cz(addr0, addr1)
}
}
pub trait CliffordExtensions: Clifford {
fn s_dag(&mut self, addr0: usize);
fn sqrt_x(&mut self, addr0: usize);
fn sqrt_x_dag(&mut self, addr0: usize);
fn sqrt_y(&mut self, addr0: usize);
fn sqrt_y_dag(&mut self, addr0: usize);
fn cy(&mut self, control: usize, target: usize);
fn zcy(&mut self, control: usize, target: usize) {
self.cy(control, target)
}
}
impl<T: PauliWordTrait> Clifford for T {
#[inline]
fn x(&mut self, _addr0: usize) {
}
#[inline]
fn y(&mut self, _addr0: usize) {
}
#[inline]
fn z(&mut self, _addr0: usize) {
}
#[inline]
fn h(&mut self, index: usize) {
if self.get_lbit(index) {
return;
}
let ix = self.get_xbit(index);
let iz = self.get_zbit(index);
self.set_xbit(index, iz);
self.set_zbit(index, ix);
self.rehash();
}
#[inline]
fn s(&mut self, index: usize) {
if self.get_lbit(index) {
return;
}
let z = self.get_xbit(index) ^ self.get_zbit(index);
self.set_zbit(index, z);
self.rehash();
}
#[inline]
fn cnot(&mut self, control: usize, target: usize) {
if self.get_lbit(control) || self.get_lbit(target) {
return;
}
let control_z = self.get_zbit(target) ^ self.get_zbit(control);
let target_x = self.get_xbit(control) ^ self.get_xbit(target);
self.set_zbit(control, control_z);
self.set_xbit(target, target_x);
self.rehash();
}
#[inline]
fn cz(&mut self, control: usize, target: usize) {
if self.get_lbit(control) || self.get_lbit(target) {
return;
}
let control_z = self.get_zbit(control) ^ self.get_xbit(target);
self.set_zbit(control, control_z);
let target_z = self.get_zbit(target) ^ self.get_xbit(control);
self.set_zbit(target, target_z);
self.rehash();
}
}
pub trait CliffordBatch: Clifford {
fn x_many(&mut self, indices: &[usize]) {
for &q in indices {
self.x(q);
}
}
fn y_many(&mut self, indices: &[usize]) {
for &q in indices {
self.y(q);
}
}
fn z_many(&mut self, indices: &[usize]) {
for &q in indices {
self.z(q);
}
}
fn h_many(&mut self, indices: &[usize]) {
for &q in indices {
self.h(q);
}
}
fn s_many(&mut self, indices: &[usize]) {
for &q in indices {
self.s(q);
}
}
fn cnot_many(&mut self, pairs: &[(usize, usize)]) {
for &(c, t) in pairs {
self.cnot(c, t);
}
}
fn cz_many(&mut self, pairs: &[(usize, usize)]) {
for &(c, t) in pairs {
self.cz(c, t);
}
}
}
pub trait CliffordExtensionsBatch: CliffordExtensions + CliffordBatch {
fn s_dag_many(&mut self, indices: &[usize]) {
for &q in indices {
self.s_dag(q);
}
}
fn sqrt_x_many(&mut self, indices: &[usize]) {
for &q in indices {
self.sqrt_x(q);
}
}
fn sqrt_x_dag_many(&mut self, indices: &[usize]) {
for &q in indices {
self.sqrt_x_dag(q);
}
}
fn sqrt_y_many(&mut self, indices: &[usize]) {
for &q in indices {
self.sqrt_y(q);
}
}
fn sqrt_y_dag_many(&mut self, indices: &[usize]) {
for &q in indices {
self.sqrt_y_dag(q);
}
}
fn cy_many(&mut self, pairs: &[(usize, usize)]) {
for &(c, t) in pairs {
self.cy(c, t);
}
}
}
impl<T: PauliWordTrait> CliffordExtensions for T {
#[inline]
fn s_dag(&mut self, addr0: usize) {
self.s(addr0);
}
#[inline]
fn sqrt_x(&mut self, addr0: usize) {
if self.get_lbit(addr0) {
return;
}
let x = self.get_xbit(addr0);
let z = self.get_zbit(addr0);
self.set_xbit(addr0, x ^ z);
self.rehash();
}
#[inline]
fn sqrt_x_dag(&mut self, addr0: usize) {
if self.get_lbit(addr0) {
return;
}
let x = self.get_xbit(addr0);
let z = self.get_zbit(addr0);
self.set_xbit(addr0, x ^ z);
self.rehash();
}
#[inline]
fn sqrt_y(&mut self, addr0: usize) {
if self.get_lbit(addr0) {
return;
}
let x = self.get_xbit(addr0);
let z = self.get_zbit(addr0);
self.set_xbit(addr0, z);
self.set_zbit(addr0, x);
self.rehash();
}
#[inline]
fn sqrt_y_dag(&mut self, addr0: usize) {
if self.get_lbit(addr0) {
return;
}
let x = self.get_xbit(addr0);
let z = self.get_zbit(addr0);
self.set_xbit(addr0, z);
self.set_zbit(addr0, x);
self.rehash();
}
#[inline]
fn cy(&mut self, addr0: usize, addr1: usize) {
if self.get_lbit(addr0) || self.get_lbit(addr1) {
return;
}
let xc = self.get_xbit(addr0);
let zc = self.get_zbit(addr0);
let xt = self.get_xbit(addr1);
let zt = self.get_zbit(addr1);
self.set_zbit(addr0, zc ^ xt ^ zt);
self.set_xbit(addr1, xt ^ xc);
self.set_zbit(addr1, zt ^ xc);
self.rehash();
}
}