qvnt 0.5.0-alpha

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

#[derive(Clone, Copy, PartialEq)]
pub struct Op {
    a_mask: Mask,
    phase: C,
}

impl Op {
    #[inline(always)]
    pub fn new(a_mask: Mask, mut phase: R) -> Self {
        phase /= 2.0;
        let phase = C::new(phase.cos(), phase.sin());
        Self { a_mask, phase }
    }
}

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 phase = self.phase;
        let psi = (psi[idx], psi[idx ^ self.a_mask]);
        if idx & self.a_mask == 0 {
            phase.im = -phase.im;
        }
        C {
            re: psi.0.re * phase.re + psi.1.re * phase.im,
            im: psi.0.im * phase.re + psi.1.im * phase.im,
        }
    }
}

impl AtomicOp for Op {
    fn name(&self) -> String {
        format!("RY{}({})", self.a_mask, 2.0 * self.phase.arg())
    }

    fn is_valid(&self) -> bool {
        self.a_mask.count_ones() == 1
    }

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

    fn this(self) -> AtomicOpDispatch {
        AtomicOpDispatch::RY(self)
    }

    fn dgr(self) -> AtomicOpDispatch {
        AtomicOpDispatch::RY(Self {
            phase: -self.phase,
            ..self
        })
    }
}

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

    const ANGLE: R = 1.23456;

    let cos = C {
        re: (0.5 * ANGLE).cos(),
        im: 0.0,
    };
    let sin = C {
        re: (0.5 * ANGLE).sin(),
        im: 0.0,
    };

    let op: SingleOp = Op::new(0b1, ANGLE).into();
    assert_eq!(op.name(), "RY1(1.23456)");
    assert_eq!(op.matrix(1), [[cos, -sin], [sin, cos]]);
}