use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum BlochMode {
#[default]
Spatial,
Planar,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum BlochPlane {
Xy,
#[default]
Xz,
Yz,
}
impl BlochPlane {
pub fn axes(self) -> [&'static str; 3] {
match self {
Self::Xy => ["x", "y", "z"],
Self::Xz => ["x", "z", "y"],
Self::Yz => ["y", "z", "x"],
}
}
pub fn project(self, v: [f64; 3]) -> [f64; 3] {
match self {
Self::Xy => v,
Self::Xz => [v[0], v[2], v[1]],
Self::Yz => [v[1], v[2], v[0]],
}
}
pub fn next(self) -> Self {
match self {
Self::Xy => Self::Xz,
Self::Xz => Self::Yz,
Self::Yz => Self::Xy,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn projections_preserve_the_hidden_component_and_squared_length() {
for plane in [BlochPlane::Xy, BlochPlane::Xz, BlochPlane::Yz] {
for v in [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.], [0.2, -0.4, 0.3]] {
let p = plane.project(v);
assert!(
(v.iter().map(|x| x * x).sum::<f64>() - p.iter().map(|x| x * x).sum::<f64>())
.abs()
< 1e-12
);
let axes = plane.axes();
for (i, name) in axes.iter().enumerate() {
assert_eq!(
p[i],
v[["x", "y", "z"].iter().position(|a| a == name).unwrap()]
);
}
}
}
}
}