1use crate::gates::Gate;
16use crate::stabilizer::PauliOp;
17
18pub struct Z
23{
24}
25
26impl Z
27{
28 pub fn new() -> Self
30 {
31 Z { }
32 }
33}
34
35impl crate::gates::Gate for Z
36{
37 fn cost(&self) -> f64
38 {
39 crate::gates::U1::cost()
40 }
41
42 fn description(&self) -> &str
43 {
44 "Z"
45 }
46
47 fn nr_affected_bits(&self) -> usize
48 {
49 1
50 }
51
52 fn matrix(&self) -> crate::cmatrix::CMatrix
53 {
54 let z = crate::cmatrix::COMPLEX_ZERO;
55 let o = crate::cmatrix::COMPLEX_ONE;
56 array![[o, z], [z, -o]]
57 }
58
59 fn apply_slice(&self, mut state: crate::cmatrix::CVecSliceMut)
60 {
61 assert!(state.len() % 2 == 0, "Number of rows is not even.");
62
63 let n = state.len() / 2;
64 state.slice_mut(s![n..]).mapv_inplace(|c| -c);
65 }
66
67 fn apply_mat_slice(&self, mut state: crate::cmatrix::CMatSliceMut)
68 {
69 assert!(state.rows() % 2 == 0, "Number of rows is not even.");
70
71 let n = state.rows() / 2;
72 state.slice_mut(s![n.., ..]).mapv_inplace(|c| -c);
73 }
74
75 fn is_stabilizer(&self) -> bool
76 {
77 true
78 }
79
80 fn conjugate(&self, ops: &mut [PauliOp]) -> crate::error::Result<bool>
81 {
82 self.check_nr_bits(ops.len())?;
83 Ok(ops[0] == PauliOp::X || ops[0] == PauliOp::Y)
84 }
85}
86
87impl crate::export::OpenQasm for Z
88{
89 fn open_qasm(&self, bit_names: &[String], bits: &[usize])
90 -> crate::error::Result<String>
91 {
92 Ok(format!("z {}", bit_names[bits[0]]))
93 }
94}
95
96impl crate::export::CQasm for Z
97{
98 fn c_qasm(&self, bit_names: &[String], bits: &[usize])
99 -> crate::error::Result<String>
100 {
101 Ok(format!("z {}", bit_names[bits[0]]))
102 }
103}
104
105impl crate::export::Latex for Z
106{
107 fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
108 -> crate::error::Result<()>
109 {
110 self.check_nr_bits(bits.len())?;
111
112 let symbol = if state.is_controlled() { r"\control \qw" } else { r"\gate{Z}" };
113 state.set_field(bits[0], String::from(symbol))
114 }
115}
116
117#[cfg(test)]
118mod tests
119{
120 use super::Z;
121 use crate::gates::{gate_test, Gate};
122 use crate::export::{Latex, LatexExportState, OpenQasm, CQasm};
123 use crate::stabilizer::PauliOp;
124
125 #[test]
126 fn test_description()
127 {
128 let gate = Z::new();
129 assert_eq!(gate.description(), "Z");
130 }
131
132 #[test]
133 fn test_cost()
134 {
135 let gate = Z::new();
136 assert_eq!(gate.cost(), 7.0);
137 }
138
139 #[test]
140 fn test_matrix()
141 {
142 let gate = Z::new();
143 let z = crate::cmatrix::COMPLEX_ZERO;
144 let o = crate::cmatrix::COMPLEX_ONE;
145 assert_complex_matrix_eq!(gate.matrix(), array![[o, z], [z, -o]]);
146 }
147
148 #[test]
149 fn test_apply()
150 {
151 let z = crate::cmatrix::COMPLEX_ZERO;
152 let o = crate::cmatrix::COMPLEX_ONE;
153 let x = crate::cmatrix::COMPLEX_HSQRT2;
154 let mut state = array![[o, z, x, x], [z, o, x, -x]];
155 let result = array![[o, z, x, x], [ z, -o, -x, x]];
156 gate_test(Z::new(), &mut state, &result);
157 }
158
159 #[test]
160 fn test_open_qasm()
161 {
162 let bit_names = [String::from("qb")];
163 let qasm = Z::new().open_qasm(&bit_names, &[0]);
164 assert_eq!(qasm, Ok(String::from("z qb")));
165 }
166
167 #[test]
168 fn test_c_qasm()
169 {
170 let bit_names = [String::from("qb")];
171 let qasm = Z::new().c_qasm(&bit_names, &[0]);
172 assert_eq!(qasm, Ok(String::from("z qb")));
173 }
174
175 #[test]
176 fn test_latex()
177 {
178 let gate = Z::new();
179 let mut state = LatexExportState::new(1, 0);
180 assert_eq!(gate.latex(&[0], &mut state), Ok(()));
181 assert_eq!(state.code(),
182r#"\Qcircuit @C=1em @R=.7em {
183 \lstick{\ket{0}} & \gate{Z} & \qw \\
184}
185"#);
186 }
187
188 #[test]
189 fn test_conjugate()
190 {
191 let mut op = [PauliOp::I];
192 assert_eq!(Z::new().conjugate(&mut op), Ok(false));
193 assert_eq!(op, [PauliOp::I]);
194
195 let mut op = [PauliOp::Z];
196 assert_eq!(Z::new().conjugate(&mut op), Ok(false));
197 assert_eq!(op, [PauliOp::Z]);
198
199 let mut op = [PauliOp::X];
200 assert_eq!(Z::new().conjugate(&mut op), Ok(true));
201 assert_eq!(op, [PauliOp::X]);
202
203 let mut op = [PauliOp::Y];
204 assert_eq!(Z::new().conjugate(&mut op), Ok(true));
205 assert_eq!(op, [PauliOp::Y]);
206 }
207}