qvnt 0.5.0-alpha

Advanced quantum computation simulator.
Documentation
use super::*;

#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Op {
    a_mask: Mask,
    i_pow: N,
}

impl Op {
    pub fn new(a_mask: Mask) -> Self {
        let i_pow = !a_mask.count_ones().wrapping_add(1) as N;
        Self { a_mask, i_pow }
    }
}

impl crate::sealed::Seal for Op {}

impl super::NativeCpuOp for Op {
    #[inline(always)]
    fn native_cpu_op(&self, psi: &[C], idx: Mask) -> C {
        let mut i_pow = self.i_pow;
        if (idx & self.a_mask).count_ones() & 1 == 0 {
            i_pow ^= 2;
        }
        crate::math::rotate(psi[idx ^ self.a_mask], i_pow)
    }
}

impl AtomicOp for Op {
    fn name(&self) -> String {
        format!("Y{}", self.a_mask)
    }

    fn acts_on(&self) -> Mask {
        self.a_mask
    }

    fn this(self) -> dispatch::AtomicOpDispatch {
        dispatch::AtomicOpDispatch::Y(self)
    }

    fn dgr(self) -> dispatch::AtomicOpDispatch {
        dispatch::AtomicOpDispatch::Y(self)
    }
}

#[cfg(test)]
#[test]
fn matrix_repr() {
    use crate::operator::single::*;

    const O: C = C { re: 0.0, im: 0.0 };
    const I: C = C { re: 1.0, im: 0.0 };
    const i: C = C { re: 0.0, im: 1.0 };

    let op: SingleOp = Op::new(0b1).into();
    assert_eq!(op.name(), "Y1");
    assert_eq!(op.matrix(1), [[O, -i], [i, O],]);

    let op: SingleOp = Op::new(0b11).into();
    assert_eq!(op.name(), "Y3");
    assert_eq!(
        op.matrix(2),
        [[O, O, O, -I], [O, O, I, O], [O, I, O, O], [-I, O, O, O],]
    );
}