paulistrings/
phase.rs

1//! [`Phase`], the `i^k` factor a Pauli product returns.
2
3use num_complex::Complex64;
4use std::ops::{Add, AddAssign};
5
6/// A phase factor `i^k` with `k ∈ {0, 1, 2, 3}`; `+` multiplies phases.
7///
8/// [`crate::PauliString::mul_assign`] returns one, and [`Phase::apply`] folds it into a coefficient.
9#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
10#[repr(transparent)]
11pub struct Phase(u8);
12
13impl Phase {
14    /// `i^0 = 1`.
15    pub const ONE: Self = Self(0);
16    /// `i^1 = i`.
17    pub const I: Self = Self(1);
18    /// `i^2 = -1`.
19    pub const MINUS_ONE: Self = Self(2);
20    /// `i^3 = -i`.
21    pub const MINUS_I: Self = Self(3);
22
23    /// Construct from a raw exponent, reduced mod 4.
24    #[inline]
25    pub const fn new(k: u8) -> Self {
26        Self(k & 3)
27    }
28
29    /// The raw exponent in `0..=3`.
30    #[inline]
31    pub const fn exponent(self) -> u8 {
32        self.0
33    }
34
35    /// `i^k` as a `Complex64`.
36    #[inline]
37    pub fn to_complex(self) -> Complex64 {
38        match self.0 {
39            0 => Complex64::new(1.0, 0.0),
40            1 => Complex64::new(0.0, 1.0),
41            2 => Complex64::new(-1.0, 0.0),
42            3 => Complex64::new(0.0, -1.0),
43            _ => unreachable!(),
44        }
45    }
46
47    /// Multiply `c` by `i^k` by a sign/swap of its parts, without a float multiply.
48    #[inline]
49    pub fn apply(self, c: Complex64) -> Complex64 {
50        match self.0 {
51            0 => c,
52            1 => Complex64::new(-c.im, c.re),
53            2 => Complex64::new(-c.re, -c.im),
54            3 => Complex64::new(c.im, -c.re),
55            _ => unreachable!(),
56        }
57    }
58}
59
60impl Add for Phase {
61    type Output = Phase;
62    #[inline]
63    fn add(self, other: Phase) -> Phase {
64        Phase((self.0 + other.0) & 3)
65    }
66}
67
68impl AddAssign for Phase {
69    #[inline]
70    fn add_assign(&mut self, other: Phase) {
71        *self = *self + other;
72    }
73}
74
75#[cfg(test)]
76mod tests;