1use crate::prelude::*;
5use num::Complex;
6
7impl<T: Config, I, C: SparseVector<Complex<T::Coeff>, I>> U3Gate<T> for GeneralizedTableau<T, I, C>
8where
9 GeneralizedTableau<T, I, C>: RotationOne<T>,
10{
11 fn u3(&mut self, addr0: usize, theta: T::Coeff, phi: T::Coeff, lambda: T::Coeff) {
12 self.rz(addr0, lambda);
14 self.ry(addr0, theta);
15 self.rz(addr0, phi);
16 }
17}
18
19#[cfg(test)]
20mod tests {
21 use super::*;
22 use ppvm_pauli_sum::config::fxhash::ByteF64;
23 use std::f64::consts::PI;
24
25 type TestConfig = ByteF64<1>;
26 type TestTableau = GeneralizedTableau<TestConfig>;
27
28 #[test]
29 fn test_u3_identity() {
30 let mut tab: TestTableau = GeneralizedTableau::new(1, 1e-12);
32 tab.u3(0, 0.0, 0.0, 0.0);
33 assert_eq!(tab.coefficients.len(), 1);
34 assert!(!tab.measure(0).unwrap());
35 }
36
37 #[test]
38 fn test_u3_x_gate() {
39 let mut tab: TestTableau = GeneralizedTableau::new(1, 1e-12);
41 tab.u3(0, PI, 0.0, 0.0);
42 assert_eq!(tab.coefficients.len(), 1);
43 assert!(tab.measure(0).unwrap());
44 }
45
46 #[test]
47 fn test_u3_superposition() {
48 let mut tab: TestTableau = GeneralizedTableau::new(1, 1e-12);
50 tab.u3(0, PI / 2.0, 0.0, 0.0);
51 assert_eq!(tab.coefficients.len(), 2);
52 }
53
54 #[test]
55 fn test_u3_matches_rz_ry_rz() {
56 let (theta, phi, lambda) = (0.34 * PI, 0.21 * PI, 0.46 * PI);
58
59 let mut tab_u3: TestTableau = GeneralizedTableau::new_with_seed(1, 1e-12, 0);
60 tab_u3.u3(0, theta, phi, lambda);
61
62 let mut tab_manual: TestTableau = GeneralizedTableau::new_with_seed(1, 1e-12, 0);
63 tab_manual.rz(0, lambda);
64 tab_manual.ry(0, theta);
65 tab_manual.rz(0, phi);
66
67 for seed in 0..200 {
68 let result_u3 = tab_u3.fork(Some(seed)).measure(0).unwrap();
69 let result_manual = tab_manual.fork(Some(seed)).measure(0).unwrap();
70 assert_eq!(result_u3, result_manual, "mismatch at seed {}", seed);
71 }
72 }
73}