1use crate::gates::Gate;
16
17pub struct T
22{
23}
24
25impl T
26{
27 pub fn new() -> Self
29 {
30 T { }
31 }
32}
33
34impl crate::gates::Gate for T
35{
36 fn cost(&self) -> f64
37 {
38 crate::gates::U1::cost()
39 }
40
41 fn description(&self) -> &str
42 {
43 "T"
44 }
45
46 fn nr_affected_bits(&self) -> usize
47 {
48 1
49 }
50
51 fn matrix(&self) -> crate::cmatrix::CMatrix
52 {
53 let z = crate::cmatrix::COMPLEX_ZERO;
54 let o = crate::cmatrix::COMPLEX_ONE;
55 let x = crate::cmatrix::COMPLEX_HSQRT2;
56 let i = crate::cmatrix::COMPLEX_I;
57 array![[o, z], [z, x+x*i]]
58 }
59
60 fn apply_slice(&self, mut state: crate::cmatrix::CVecSliceMut)
61 {
62 assert!(state.len() % 2 == 0, "Number of rows is not even.");
63
64 let n = state.len() / 2;
65 let mut slice = state.slice_mut(s![n..]);
66 slice *= num_complex::Complex::from_polar(&1.0, &::std::f64::consts::FRAC_PI_4);
67 }
68
69 fn apply_mat_slice(&self, mut state: crate::cmatrix::CMatSliceMut)
70 {
71 assert!(state.rows() % 2 == 0, "Number of rows is not even.");
72
73 let n = state.rows() / 2;
74 let mut slice = state.slice_mut(s![n.., ..]);
75 slice *= num_complex::Complex::from_polar(&1.0, &::std::f64::consts::FRAC_PI_4);
76 }
77}
78
79impl crate::export::OpenQasm for T
80{
81 fn open_qasm(&self, bit_names: &[String], bits: &[usize])
82 -> crate::error::Result<String>
83 {
84 Ok(format!("t {}", bit_names[bits[0]]))
85 }
86}
87
88impl crate::export::CQasm for T
89{
90 fn c_qasm(&self, bit_names: &[String], bits: &[usize])
91 -> crate::error::Result<String>
92 {
93 Ok(format!("t {}", bit_names[bits[0]]))
94 }
95}
96
97impl crate::export::Latex for T
98{
99 fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
100 -> crate::error::Result<()>
101 {
102 self.check_nr_bits(bits.len())?;
103 state.add_block_gate(bits, "T")
104 }
105}
106
107pub struct Tdg
112{
113}
114
115impl Tdg
116{
117 pub fn new() -> Self
119 {
120 Tdg { }
121 }
122}
123
124impl crate::gates::Gate for Tdg
125{
126 fn cost(&self) -> f64
127 {
128 crate::gates::U1::cost()
129 }
130
131 fn description(&self) -> &str
132 {
133 "T†"
134 }
135
136 fn nr_affected_bits(&self) -> usize
137 {
138 1
139 }
140
141 fn matrix(&self) -> crate::cmatrix::CMatrix
142 {
143 let z = crate::cmatrix::COMPLEX_ZERO;
144 let o = crate::cmatrix::COMPLEX_ONE;
145 let x = crate::cmatrix::COMPLEX_HSQRT2;
146 let i = crate::cmatrix::COMPLEX_I;
147 array![[o, z], [z, x-x*i]]
148 }
149
150 fn apply_slice(&self, mut state: crate::cmatrix::CVecSliceMut)
151 {
152 assert!(state.len() % 2 == 0, "Number of rows is not even.");
153
154 let n = state.len() / 2;
155 let mut slice = state.slice_mut(s![n..]);
156 slice *= num_complex::Complex::from_polar(&1.0, &-::std::f64::consts::FRAC_PI_4);
157 }
158
159 fn apply_mat_slice(&self, mut state: crate::cmatrix::CMatSliceMut)
160 {
161 assert!(state.rows() % 2 == 0, "Number of rows is not even.");
162
163 let n = state.rows() / 2;
164 let mut slice = state.slice_mut(s![n.., ..]);
165 slice *= num_complex::Complex::from_polar(&1.0, &-::std::f64::consts::FRAC_PI_4);
166 }
167}
168
169impl crate::export::OpenQasm for Tdg
170{
171 fn open_qasm(&self, bit_names: &[String], bits: &[usize])
172 -> crate::error::Result<String>
173 {
174 Ok(format!("tdg {}", bit_names[bits[0]]))
175 }
176}
177
178impl crate::export::CQasm for Tdg
179{
180 fn c_qasm(&self, bit_names: &[String], bits: &[usize])
181 -> crate::error::Result<String>
182 {
183 Ok(format!("tdag {}", bit_names[bits[0]]))
184 }
185}
186
187impl crate::export::Latex for Tdg
188{
189 fn latex(&self, bits: &[usize], state: &mut crate::export::LatexExportState)
190 -> crate::error::Result<()>
191 {
192 self.check_nr_bits(bits.len())?;
193 state.add_block_gate(bits, r"T^\dagger")
194 }
195}
196
197#[cfg(test)]
198mod tests
199{
200 use super::{T, Tdg};
201 use crate::gates::{gate_test, Gate};
202 use crate::export::{Latex, LatexExportState, OpenQasm, CQasm};
203
204 #[test]
205 fn test_description()
206 {
207 let gate = T::new();
208 assert_eq!(gate.description(), "T");
209 let gate = Tdg::new();
210 assert_eq!(gate.description(), "T†");
211 }
212
213 #[test]
214 fn test_cost()
215 {
216 let gate = T::new();
217 assert_eq!(gate.cost(), 7.0);
218 let gate = Tdg::new();
219 assert_eq!(gate.cost(), 7.0);
220 }
221
222 #[test]
223 fn test_matrix()
224 {
225 let z = crate::cmatrix::COMPLEX_ZERO;
226 let o = crate::cmatrix::COMPLEX_ONE;
227 let t = num_complex::Complex::from_polar(&1.0, &::std::f64::consts::FRAC_PI_4);
228
229 let gate = T::new();
230 assert_complex_matrix_eq!(gate.matrix(), array![[o, z], [z, t]]);
231
232 let gate = Tdg::new();
233 assert_complex_matrix_eq!(gate.matrix(), array![[o, z], [z, t.conj()]]);
234 }
235
236 #[test]
237 fn test_apply()
238 {
239 let z = crate::cmatrix::COMPLEX_ZERO;
240 let o = crate::cmatrix::COMPLEX_ONE;
241 let h = 0.5 * o;
242 let x = crate::cmatrix::COMPLEX_HSQRT2;
243 let t = num_complex::Complex::from_polar(&1.0, &::std::f64::consts::FRAC_PI_4);
244 let td = t.conj();
245
246 let mut state = array![
247 [o, z, x, h, z],
248 [z, o, z, -h, z],
249 [z, z, x, h, z],
250 [z, z, z, -h, o]
251 ];
252 let result = array![
253 [o, z, x, h, z],
254 [z, o, z, -h, z],
255 [z, z, t*x, t*h, z],
256 [z, z, z, -t*h, t]
257 ];
258 gate_test(T::new(), &mut state, &result);
259
260 let mut state = array![
261 [o, z, x, h, z],
262 [z, o, z, -h, z],
263 [z, z, x, h, z],
264 [z, z, z, -h, o]
265 ];
266 let result = array![
267 [o, z, x, h, z],
268 [z, o, z, -h, z],
269 [z, z, td*x, td*h, z],
270 [z, z, z, -td*h, td]
271 ];
272 gate_test(Tdg::new(), &mut state, &result);
273 }
274
275 #[test]
276 fn test_apply_mat()
277 {
278 let z = crate::cmatrix::COMPLEX_ZERO;
279 let o = crate::cmatrix::COMPLEX_ONE;
280 let h = 0.5 * o;
281 let x = crate::cmatrix::COMPLEX_HSQRT2;
282 let t = num_complex::Complex::from_polar(&1.0, &::std::f64::consts::FRAC_PI_4);
283 let td = t.conj();
284
285 let mut state = array![
286 [o, z, x, h, z],
287 [z, o, z, -h, z],
288 [z, z, x, h, z],
289 [z, z, z, -h, o]
290 ];
291 T::new().apply_mat(&mut state);
292 assert_complex_matrix_eq!(&state, &array![
293 [o, z, x, h, z],
294 [z, o, z, -h, z],
295 [z, z, t*x, t*h, z],
296 [z, z, z, -t*h, t]
297 ]);
298
299 let mut state = array![
300 [o, z, x, h, z],
301 [z, o, z, -h, z],
302 [z, z, x, h, z],
303 [z, z, z, -h, o]
304 ];
305 Tdg::new().apply_mat(&mut state);
306 assert_complex_matrix_eq!(&state, &array![
307 [o, z, x, h, z],
308 [z, o, z, -h, z],
309 [z, z, td*x, td*h, z],
310 [z, z, z, -td*h, td]
311 ]);
312 }
313
314 #[test]
315 fn test_open_qasm()
316 {
317 let bit_names = [String::from("qb")];
318 let qasm = T::new().open_qasm(&bit_names, &[0]);
319 assert_eq!(qasm, Ok(String::from("t qb")));
320 let qasm = Tdg::new().open_qasm(&bit_names, &[0]);
321 assert_eq!(qasm, Ok(String::from("tdg qb")));
322 }
323
324 #[test]
325 fn test_c_qasm()
326 {
327 let bit_names = [String::from("qb")];
328 let qasm = T::new().c_qasm(&bit_names, &[0]);
329 assert_eq!(qasm, Ok(String::from("t qb")));
330 let qasm = Tdg::new().c_qasm(&bit_names, &[0]);
331 assert_eq!(qasm, Ok(String::from("tdag qb")));
332 }
333
334 #[test]
335 fn test_latex()
336 {
337 let gate = T::new();
338 let mut state = LatexExportState::new(1, 0);
339 assert_eq!(gate.latex(&[0], &mut state), Ok(()));
340 assert_eq!(state.code(),
341r#"\Qcircuit @C=1em @R=.7em {
342 \lstick{\ket{0}} & \gate{T} & \qw \\
343}
344"#);
345
346 let gate = Tdg::new();
347 let mut state = LatexExportState::new(1, 0);
348 assert_eq!(gate.latex(&[0], &mut state), Ok(()));
349 assert_eq!(state.code(),
350r#"\Qcircuit @C=1em @R=.7em {
351 \lstick{\ket{0}} & \gate{T^\dagger} & \qw \\
352}
353"#);
354 }
355}