1use crate::error::QuantRS2Result;
6use crate::qubit::QubitId;
7use scirs2_core::Complex64;
8use std::any::Any;
9use std::f64::consts::PI;
10use std::fmt::Debug;
11
12macro_rules! impl_clone_gate {
14 () => {
15 fn clone_gate(&self) -> Box<dyn GateOp> {
16 Box::new(self.clone())
17 }
18 };
19}
20pub trait GateOp: Debug + Send + Sync {
22 fn name(&self) -> &'static str;
24 fn qubits(&self) -> Vec<QubitId>;
26 fn num_qubits(&self) -> usize {
28 self.qubits().len()
29 }
30 fn is_parameterized(&self) -> bool {
32 false
33 }
34 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>>;
36 fn as_any(&self) -> &dyn Any;
38 fn clone_gate(&self) -> Box<dyn GateOp>;
40}
41impl Clone for Box<dyn GateOp> {
43 fn clone(&self) -> Self {
44 self.clone_gate()
45 }
46}
47pub mod single {
49 use super::*;
50 use super::*;
51 #[derive(Debug, Clone, Copy)]
53 pub struct Hadamard {
54 pub target: QubitId,
56 }
57 impl GateOp for Hadamard {
58 fn name(&self) -> &'static str {
59 "H"
60 }
61 fn qubits(&self) -> Vec<QubitId> {
62 vec![self.target]
63 }
64 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
65 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
66 Ok(vec![
67 Complex64::new(sqrt2_inv, 0.0),
68 Complex64::new(sqrt2_inv, 0.0),
69 Complex64::new(sqrt2_inv, 0.0),
70 Complex64::new(-sqrt2_inv, 0.0),
71 ])
72 }
73 fn as_any(&self) -> &dyn Any {
74 self
75 }
76 impl_clone_gate!();
77 }
78 #[derive(Debug, Clone, Copy)]
80 pub struct PauliX {
81 pub target: QubitId,
83 }
84 impl GateOp for PauliX {
85 fn name(&self) -> &'static str {
86 "X"
87 }
88 fn qubits(&self) -> Vec<QubitId> {
89 vec![self.target]
90 }
91 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
92 Ok(vec![
93 Complex64::new(0.0, 0.0),
94 Complex64::new(1.0, 0.0),
95 Complex64::new(1.0, 0.0),
96 Complex64::new(0.0, 0.0),
97 ])
98 }
99 fn as_any(&self) -> &dyn Any {
100 self
101 }
102 impl_clone_gate!();
103 }
104 #[derive(Debug, Clone, Copy)]
106 pub struct PauliY {
107 pub target: QubitId,
109 }
110 impl GateOp for PauliY {
111 fn name(&self) -> &'static str {
112 "Y"
113 }
114 fn qubits(&self) -> Vec<QubitId> {
115 vec![self.target]
116 }
117 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
118 Ok(vec![
119 Complex64::new(0.0, 0.0),
120 Complex64::new(0.0, -1.0),
121 Complex64::new(0.0, 1.0),
122 Complex64::new(0.0, 0.0),
123 ])
124 }
125 fn as_any(&self) -> &dyn Any {
126 self
127 }
128 impl_clone_gate!();
129 }
130 #[derive(Debug, Clone, Copy)]
132 pub struct PauliZ {
133 pub target: QubitId,
135 }
136 impl GateOp for PauliZ {
137 fn name(&self) -> &'static str {
138 "Z"
139 }
140 fn qubits(&self) -> Vec<QubitId> {
141 vec![self.target]
142 }
143 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
144 Ok(vec![
145 Complex64::new(1.0, 0.0),
146 Complex64::new(0.0, 0.0),
147 Complex64::new(0.0, 0.0),
148 Complex64::new(-1.0, 0.0),
149 ])
150 }
151 fn as_any(&self) -> &dyn Any {
152 self
153 }
154 impl_clone_gate!();
155 }
156 #[derive(Debug, Clone, Copy)]
158 pub struct RotationX {
159 pub target: QubitId,
161 pub theta: f64,
163 }
164 impl GateOp for RotationX {
165 fn name(&self) -> &'static str {
166 "RX"
167 }
168 fn qubits(&self) -> Vec<QubitId> {
169 vec![self.target]
170 }
171 fn is_parameterized(&self) -> bool {
172 true
173 }
174 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
175 let cos = (self.theta / 2.0).cos();
176 let sin = (self.theta / 2.0).sin();
177 Ok(vec![
178 Complex64::new(cos, 0.0),
179 Complex64::new(0.0, -sin),
180 Complex64::new(0.0, -sin),
181 Complex64::new(cos, 0.0),
182 ])
183 }
184 fn as_any(&self) -> &dyn Any {
185 self
186 }
187 impl_clone_gate!();
188 }
189 #[derive(Debug, Clone, Copy)]
191 pub struct RotationY {
192 pub target: QubitId,
194 pub theta: f64,
196 }
197 impl GateOp for RotationY {
198 fn name(&self) -> &'static str {
199 "RY"
200 }
201 fn qubits(&self) -> Vec<QubitId> {
202 vec![self.target]
203 }
204 fn is_parameterized(&self) -> bool {
205 true
206 }
207 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
208 let cos = (self.theta / 2.0).cos();
209 let sin = (self.theta / 2.0).sin();
210 Ok(vec![
211 Complex64::new(cos, 0.0),
212 Complex64::new(-sin, 0.0),
213 Complex64::new(sin, 0.0),
214 Complex64::new(cos, 0.0),
215 ])
216 }
217 fn as_any(&self) -> &dyn Any {
218 self
219 }
220 impl_clone_gate!();
221 }
222 #[derive(Debug, Clone, Copy)]
224 pub struct RotationZ {
225 pub target: QubitId,
227 pub theta: f64,
229 }
230 impl GateOp for RotationZ {
231 fn name(&self) -> &'static str {
232 "RZ"
233 }
234 fn qubits(&self) -> Vec<QubitId> {
235 vec![self.target]
236 }
237 fn is_parameterized(&self) -> bool {
238 true
239 }
240 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
241 let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
242 let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
243 Ok(vec![
245 phase,
246 Complex64::new(0.0, 0.0),
247 Complex64::new(0.0, 0.0),
248 phase_conj,
249 ])
250 }
251 fn as_any(&self) -> &dyn Any {
252 self
253 }
254 impl_clone_gate!();
255 }
256 #[derive(Debug, Clone, Copy)]
258 pub struct Phase {
259 pub target: QubitId,
261 }
262 impl GateOp for Phase {
263 fn name(&self) -> &'static str {
264 "S"
265 }
266 fn qubits(&self) -> Vec<QubitId> {
267 vec![self.target]
268 }
269 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
270 Ok(vec![
271 Complex64::new(1.0, 0.0),
272 Complex64::new(0.0, 0.0),
273 Complex64::new(0.0, 0.0),
274 Complex64::new(0.0, 1.0),
275 ])
276 }
277 fn as_any(&self) -> &dyn Any {
278 self
279 }
280 impl_clone_gate!();
281 }
282 #[derive(Debug, Clone, Copy)]
284 pub struct T {
285 pub target: QubitId,
287 }
288 impl GateOp for T {
289 fn name(&self) -> &'static str {
290 "T"
291 }
292 fn qubits(&self) -> Vec<QubitId> {
293 vec![self.target]
294 }
295 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
296 let phase = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
297 Ok(vec![
298 Complex64::new(1.0, 0.0),
299 Complex64::new(0.0, 0.0),
300 Complex64::new(0.0, 0.0),
301 phase,
302 ])
303 }
304 fn as_any(&self) -> &dyn Any {
305 self
306 }
307 impl_clone_gate!();
308 }
309 #[derive(Debug, Clone, Copy)]
311 pub struct TDagger {
312 pub target: QubitId,
314 }
315 impl GateOp for TDagger {
316 fn name(&self) -> &'static str {
317 "T†"
318 }
319 fn qubits(&self) -> Vec<QubitId> {
320 vec![self.target]
321 }
322 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
323 let phase = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
324 Ok(vec![
325 Complex64::new(1.0, 0.0),
326 Complex64::new(0.0, 0.0),
327 Complex64::new(0.0, 0.0),
328 phase,
329 ])
330 }
331 fn as_any(&self) -> &dyn Any {
332 self
333 }
334 impl_clone_gate!();
335 }
336 #[derive(Debug, Clone, Copy)]
338 pub struct PhaseDagger {
339 pub target: QubitId,
341 }
342 impl GateOp for PhaseDagger {
343 fn name(&self) -> &'static str {
344 "S†"
345 }
346 fn qubits(&self) -> Vec<QubitId> {
347 vec![self.target]
348 }
349 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
350 Ok(vec![
351 Complex64::new(1.0, 0.0),
352 Complex64::new(0.0, 0.0),
353 Complex64::new(0.0, 0.0),
354 Complex64::new(0.0, -1.0),
355 ])
356 }
357 fn as_any(&self) -> &dyn Any {
358 self
359 }
360 impl_clone_gate!();
361 }
362 #[derive(Debug, Clone, Copy)]
364 pub struct SqrtX {
365 pub target: QubitId,
367 }
368 impl GateOp for SqrtX {
369 fn name(&self) -> &'static str {
370 "√X"
371 }
372 fn qubits(&self) -> Vec<QubitId> {
373 vec![self.target]
374 }
375 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
376 let half_plus_i_half = Complex64::new(0.5, 0.5);
377 let half_minus_i_half = Complex64::new(0.5, -0.5);
378 Ok(vec![
379 half_plus_i_half,
380 half_minus_i_half,
381 half_minus_i_half,
382 half_plus_i_half,
383 ])
384 }
385 fn as_any(&self) -> &dyn Any {
386 self
387 }
388 impl_clone_gate!();
389 }
390 #[derive(Debug, Clone, Copy)]
392 pub struct SqrtXDagger {
393 pub target: QubitId,
395 }
396 impl GateOp for SqrtXDagger {
397 fn name(&self) -> &'static str {
398 "√X†"
399 }
400 fn qubits(&self) -> Vec<QubitId> {
401 vec![self.target]
402 }
403 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
404 let half_minus_i_half = Complex64::new(0.5, -0.5);
405 let half_plus_i_half = Complex64::new(0.5, 0.5);
406 Ok(vec![
407 half_minus_i_half,
408 half_plus_i_half,
409 half_plus_i_half,
410 half_minus_i_half,
411 ])
412 }
413 fn as_any(&self) -> &dyn Any {
414 self
415 }
416 impl_clone_gate!();
417 }
418 #[derive(Debug, Clone, Copy)]
423 pub struct UGate {
424 pub target: QubitId,
426 pub theta: f64,
428 pub phi: f64,
430 pub lambda: f64,
432 }
433 impl GateOp for UGate {
434 fn name(&self) -> &'static str {
435 "U"
436 }
437 fn qubits(&self) -> Vec<QubitId> {
438 vec![self.target]
439 }
440 fn is_parameterized(&self) -> bool {
441 true
442 }
443 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
444 let cos = (self.theta / 2.0).cos();
445 let sin = (self.theta / 2.0).sin();
446 let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
447 let exp_i_phi = Complex64::new(0.0, self.phi).exp();
448 let exp_i_phi_lambda = Complex64::new(0.0, self.phi + self.lambda).exp();
449 Ok(vec![
450 Complex64::new(cos, 0.0),
451 -exp_i_lambda * sin,
452 exp_i_phi * sin,
453 exp_i_phi_lambda * cos,
454 ])
455 }
456 fn as_any(&self) -> &dyn Any {
457 self
458 }
459 impl_clone_gate!();
460 }
461 #[derive(Debug, Clone, Copy)]
465 pub struct PGate {
466 pub target: QubitId,
468 pub lambda: f64,
470 }
471 impl GateOp for PGate {
472 fn name(&self) -> &'static str {
473 "P"
474 }
475 fn qubits(&self) -> Vec<QubitId> {
476 vec![self.target]
477 }
478 fn is_parameterized(&self) -> bool {
479 true
480 }
481 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
482 let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
483 Ok(vec![
484 Complex64::new(1.0, 0.0),
485 Complex64::new(0.0, 0.0),
486 Complex64::new(0.0, 0.0),
487 exp_i_lambda,
488 ])
489 }
490 fn as_any(&self) -> &dyn Any {
491 self
492 }
493 impl_clone_gate!();
494 }
495 #[derive(Debug, Clone, Copy)]
497 pub struct Identity {
498 pub target: QubitId,
500 }
501 impl GateOp for Identity {
502 fn name(&self) -> &'static str {
503 "I"
504 }
505 fn qubits(&self) -> Vec<QubitId> {
506 vec![self.target]
507 }
508 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
509 Ok(vec![
510 Complex64::new(1.0, 0.0),
511 Complex64::new(0.0, 0.0),
512 Complex64::new(0.0, 0.0),
513 Complex64::new(1.0, 0.0),
514 ])
515 }
516 fn as_any(&self) -> &dyn Any {
517 self
518 }
519 impl_clone_gate!();
520 }
521}
522pub mod multi {
524 use super::*;
525 #[derive(Debug, Clone, Copy)]
527 pub struct CNOT {
528 pub control: QubitId,
530 pub target: QubitId,
532 }
533 impl GateOp for CNOT {
534 fn name(&self) -> &'static str {
535 "CNOT"
536 }
537 fn qubits(&self) -> Vec<QubitId> {
538 vec![self.control, self.target]
539 }
540 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
541 Ok(vec![
542 Complex64::new(1.0, 0.0),
543 Complex64::new(0.0, 0.0),
544 Complex64::new(0.0, 0.0),
545 Complex64::new(0.0, 0.0),
546 Complex64::new(0.0, 0.0),
547 Complex64::new(1.0, 0.0),
548 Complex64::new(0.0, 0.0),
549 Complex64::new(0.0, 0.0),
550 Complex64::new(0.0, 0.0),
551 Complex64::new(0.0, 0.0),
552 Complex64::new(0.0, 0.0),
553 Complex64::new(1.0, 0.0),
554 Complex64::new(0.0, 0.0),
555 Complex64::new(0.0, 0.0),
556 Complex64::new(1.0, 0.0),
557 Complex64::new(0.0, 0.0),
558 ])
559 }
560 fn as_any(&self) -> &dyn Any {
561 self
562 }
563 impl_clone_gate!();
564 }
565 #[derive(Debug, Clone, Copy)]
567 pub struct CZ {
568 pub control: QubitId,
570 pub target: QubitId,
572 }
573 impl GateOp for CZ {
574 fn name(&self) -> &'static str {
575 "CZ"
576 }
577 fn qubits(&self) -> Vec<QubitId> {
578 vec![self.control, self.target]
579 }
580 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
581 Ok(vec![
582 Complex64::new(1.0, 0.0),
583 Complex64::new(0.0, 0.0),
584 Complex64::new(0.0, 0.0),
585 Complex64::new(0.0, 0.0),
586 Complex64::new(0.0, 0.0),
587 Complex64::new(1.0, 0.0),
588 Complex64::new(0.0, 0.0),
589 Complex64::new(0.0, 0.0),
590 Complex64::new(0.0, 0.0),
591 Complex64::new(0.0, 0.0),
592 Complex64::new(1.0, 0.0),
593 Complex64::new(0.0, 0.0),
594 Complex64::new(0.0, 0.0),
595 Complex64::new(0.0, 0.0),
596 Complex64::new(0.0, 0.0),
597 Complex64::new(-1.0, 0.0),
598 ])
599 }
600 fn as_any(&self) -> &dyn Any {
601 self
602 }
603 impl_clone_gate!();
604 }
605 #[derive(Debug, Clone, Copy)]
607 pub struct SWAP {
608 pub qubit1: QubitId,
610 pub qubit2: QubitId,
612 }
613 impl GateOp for SWAP {
614 fn name(&self) -> &'static str {
615 "SWAP"
616 }
617 fn qubits(&self) -> Vec<QubitId> {
618 vec![self.qubit1, self.qubit2]
619 }
620 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
621 Ok(vec![
622 Complex64::new(1.0, 0.0),
623 Complex64::new(0.0, 0.0),
624 Complex64::new(0.0, 0.0),
625 Complex64::new(0.0, 0.0),
626 Complex64::new(0.0, 0.0),
627 Complex64::new(0.0, 0.0),
628 Complex64::new(1.0, 0.0),
629 Complex64::new(0.0, 0.0),
630 Complex64::new(0.0, 0.0),
631 Complex64::new(1.0, 0.0),
632 Complex64::new(0.0, 0.0),
633 Complex64::new(0.0, 0.0),
634 Complex64::new(0.0, 0.0),
635 Complex64::new(0.0, 0.0),
636 Complex64::new(0.0, 0.0),
637 Complex64::new(1.0, 0.0),
638 ])
639 }
640 fn as_any(&self) -> &dyn Any {
641 self
642 }
643 impl_clone_gate!();
644 }
645 #[derive(Debug, Clone, Copy)]
647 pub struct CY {
648 pub control: QubitId,
650 pub target: QubitId,
652 }
653 impl GateOp for CY {
654 fn name(&self) -> &'static str {
655 "CY"
656 }
657 fn qubits(&self) -> Vec<QubitId> {
658 vec![self.control, self.target]
659 }
660 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
661 Ok(vec![
662 Complex64::new(1.0, 0.0),
663 Complex64::new(0.0, 0.0),
664 Complex64::new(0.0, 0.0),
665 Complex64::new(0.0, 0.0),
666 Complex64::new(0.0, 0.0),
667 Complex64::new(1.0, 0.0),
668 Complex64::new(0.0, 0.0),
669 Complex64::new(0.0, 0.0),
670 Complex64::new(0.0, 0.0),
671 Complex64::new(0.0, 0.0),
672 Complex64::new(0.0, 0.0),
673 Complex64::new(0.0, -1.0),
674 Complex64::new(0.0, 0.0),
675 Complex64::new(0.0, 0.0),
676 Complex64::new(0.0, 1.0),
677 Complex64::new(0.0, 0.0),
678 ])
679 }
680 fn as_any(&self) -> &dyn Any {
681 self
682 }
683 impl_clone_gate!();
684 }
685 #[derive(Debug, Clone, Copy)]
687 pub struct CH {
688 pub control: QubitId,
690 pub target: QubitId,
692 }
693 impl GateOp for CH {
694 fn name(&self) -> &'static str {
695 "CH"
696 }
697 fn qubits(&self) -> Vec<QubitId> {
698 vec![self.control, self.target]
699 }
700 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
701 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
702 Ok(vec![
703 Complex64::new(1.0, 0.0),
704 Complex64::new(0.0, 0.0),
705 Complex64::new(0.0, 0.0),
706 Complex64::new(0.0, 0.0),
707 Complex64::new(0.0, 0.0),
708 Complex64::new(1.0, 0.0),
709 Complex64::new(0.0, 0.0),
710 Complex64::new(0.0, 0.0),
711 Complex64::new(0.0, 0.0),
712 Complex64::new(0.0, 0.0),
713 Complex64::new(sqrt2_inv, 0.0),
714 Complex64::new(sqrt2_inv, 0.0),
715 Complex64::new(0.0, 0.0),
716 Complex64::new(0.0, 0.0),
717 Complex64::new(sqrt2_inv, 0.0),
718 Complex64::new(-sqrt2_inv, 0.0),
719 ])
720 }
721 fn as_any(&self) -> &dyn Any {
722 self
723 }
724 impl_clone_gate!();
725 }
726 #[derive(Debug, Clone, Copy)]
728 pub struct CS {
729 pub control: QubitId,
731 pub target: QubitId,
733 }
734 impl GateOp for CS {
735 fn name(&self) -> &'static str {
736 "CS"
737 }
738 fn qubits(&self) -> Vec<QubitId> {
739 vec![self.control, self.target]
740 }
741 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
742 Ok(vec![
743 Complex64::new(1.0, 0.0),
744 Complex64::new(0.0, 0.0),
745 Complex64::new(0.0, 0.0),
746 Complex64::new(0.0, 0.0),
747 Complex64::new(0.0, 0.0),
748 Complex64::new(1.0, 0.0),
749 Complex64::new(0.0, 0.0),
750 Complex64::new(0.0, 0.0),
751 Complex64::new(0.0, 0.0),
752 Complex64::new(0.0, 0.0),
753 Complex64::new(1.0, 0.0),
754 Complex64::new(0.0, 0.0),
755 Complex64::new(0.0, 0.0),
756 Complex64::new(0.0, 0.0),
757 Complex64::new(0.0, 0.0),
758 Complex64::new(0.0, 1.0),
759 ])
760 }
761 fn as_any(&self) -> &dyn Any {
762 self
763 }
764 impl_clone_gate!();
765 }
766 #[derive(Debug, Clone, Copy)]
768 pub struct Toffoli {
769 pub control1: QubitId,
771 pub control2: QubitId,
773 pub target: QubitId,
775 }
776 impl GateOp for Toffoli {
777 fn name(&self) -> &'static str {
778 "Toffoli"
779 }
780 fn qubits(&self) -> Vec<QubitId> {
781 vec![self.control1, self.control2, self.target]
782 }
783 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
784 Err(crate::error::QuantRS2Error::UnsupportedOperation(
785 "Direct matrix representation of Toffoli gate not supported. \
786 Use gate decomposition."
787 .into(),
788 ))
789 }
790 fn as_any(&self) -> &dyn Any {
791 self
792 }
793 impl_clone_gate!();
794 }
795 #[derive(Debug, Clone, Copy)]
797 pub struct Fredkin {
798 pub control: QubitId,
800 pub target1: QubitId,
802 pub target2: QubitId,
804 }
805 impl GateOp for Fredkin {
806 fn name(&self) -> &'static str {
807 "Fredkin"
808 }
809 fn qubits(&self) -> Vec<QubitId> {
810 vec![self.control, self.target1, self.target2]
811 }
812 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
813 Err(crate::error::QuantRS2Error::UnsupportedOperation(
814 "Direct matrix representation of Fredkin gate not supported. \
815 Use gate decomposition."
816 .into(),
817 ))
818 }
819 fn as_any(&self) -> &dyn Any {
820 self
821 }
822 impl_clone_gate!();
823 }
824 #[derive(Debug, Clone, Copy)]
826 pub struct CRX {
827 pub control: QubitId,
829 pub target: QubitId,
831 pub theta: f64,
833 }
834 impl GateOp for CRX {
835 fn name(&self) -> &'static str {
836 "CRX"
837 }
838 fn qubits(&self) -> Vec<QubitId> {
839 vec![self.control, self.target]
840 }
841 fn is_parameterized(&self) -> bool {
842 true
843 }
844 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
845 let cos = (self.theta / 2.0).cos();
846 let sin = (self.theta / 2.0).sin();
847 Ok(vec![
848 Complex64::new(1.0, 0.0),
849 Complex64::new(0.0, 0.0),
850 Complex64::new(0.0, 0.0),
851 Complex64::new(0.0, 0.0),
852 Complex64::new(0.0, 0.0),
853 Complex64::new(1.0, 0.0),
854 Complex64::new(0.0, 0.0),
855 Complex64::new(0.0, 0.0),
856 Complex64::new(0.0, 0.0),
857 Complex64::new(0.0, 0.0),
858 Complex64::new(cos, 0.0),
859 Complex64::new(0.0, -sin),
860 Complex64::new(0.0, 0.0),
861 Complex64::new(0.0, 0.0),
862 Complex64::new(0.0, -sin),
863 Complex64::new(cos, 0.0),
864 ])
865 }
866 fn as_any(&self) -> &dyn Any {
867 self
868 }
869 impl_clone_gate!();
870 }
871 #[derive(Debug, Clone, Copy)]
873 pub struct CRY {
874 pub control: QubitId,
876 pub target: QubitId,
878 pub theta: f64,
880 }
881 impl GateOp for CRY {
882 fn name(&self) -> &'static str {
883 "CRY"
884 }
885 fn qubits(&self) -> Vec<QubitId> {
886 vec![self.control, self.target]
887 }
888 fn is_parameterized(&self) -> bool {
889 true
890 }
891 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
892 let cos = (self.theta / 2.0).cos();
893 let sin = (self.theta / 2.0).sin();
894 Ok(vec![
895 Complex64::new(1.0, 0.0),
896 Complex64::new(0.0, 0.0),
897 Complex64::new(0.0, 0.0),
898 Complex64::new(0.0, 0.0),
899 Complex64::new(0.0, 0.0),
900 Complex64::new(1.0, 0.0),
901 Complex64::new(0.0, 0.0),
902 Complex64::new(0.0, 0.0),
903 Complex64::new(0.0, 0.0),
904 Complex64::new(0.0, 0.0),
905 Complex64::new(cos, 0.0),
906 Complex64::new(-sin, 0.0),
907 Complex64::new(0.0, 0.0),
908 Complex64::new(0.0, 0.0),
909 Complex64::new(sin, 0.0),
910 Complex64::new(cos, 0.0),
911 ])
912 }
913 fn as_any(&self) -> &dyn Any {
914 self
915 }
916 impl_clone_gate!();
917 }
918 #[derive(Debug, Clone, Copy)]
920 pub struct CRZ {
921 pub control: QubitId,
923 pub target: QubitId,
925 pub theta: f64,
927 }
928 impl GateOp for CRZ {
929 fn name(&self) -> &'static str {
930 "CRZ"
931 }
932 fn qubits(&self) -> Vec<QubitId> {
933 vec![self.control, self.target]
934 }
935 fn is_parameterized(&self) -> bool {
936 true
937 }
938 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
939 let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
940 let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
941 Ok(vec![
944 Complex64::new(1.0, 0.0),
945 Complex64::new(0.0, 0.0),
946 Complex64::new(0.0, 0.0),
947 Complex64::new(0.0, 0.0),
948 Complex64::new(0.0, 0.0),
949 Complex64::new(1.0, 0.0),
950 Complex64::new(0.0, 0.0),
951 Complex64::new(0.0, 0.0),
952 Complex64::new(0.0, 0.0),
953 Complex64::new(0.0, 0.0),
954 phase,
955 Complex64::new(0.0, 0.0),
956 Complex64::new(0.0, 0.0),
957 Complex64::new(0.0, 0.0),
958 Complex64::new(0.0, 0.0),
959 phase_conj,
960 ])
961 }
962 fn as_any(&self) -> &dyn Any {
963 self
964 }
965 impl_clone_gate!();
966 }
967 #[derive(Debug, Clone, Copy)]
974 pub struct ISwap {
975 pub qubit1: QubitId,
977 pub qubit2: QubitId,
979 }
980 impl GateOp for ISwap {
981 fn name(&self) -> &'static str {
982 "iSWAP"
983 }
984 fn qubits(&self) -> Vec<QubitId> {
985 vec![self.qubit1, self.qubit2]
986 }
987 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
988 Ok(vec![
989 Complex64::new(1.0, 0.0),
990 Complex64::new(0.0, 0.0),
991 Complex64::new(0.0, 0.0),
992 Complex64::new(0.0, 0.0),
993 Complex64::new(0.0, 0.0),
994 Complex64::new(0.0, 0.0),
995 Complex64::new(0.0, 1.0),
996 Complex64::new(0.0, 0.0),
997 Complex64::new(0.0, 0.0),
998 Complex64::new(0.0, 1.0),
999 Complex64::new(0.0, 0.0),
1000 Complex64::new(0.0, 0.0),
1001 Complex64::new(0.0, 0.0),
1002 Complex64::new(0.0, 0.0),
1003 Complex64::new(0.0, 0.0),
1004 Complex64::new(1.0, 0.0),
1005 ])
1006 }
1007 fn as_any(&self) -> &dyn Any {
1008 self
1009 }
1010 impl_clone_gate!();
1011 }
1012 #[derive(Debug, Clone, Copy)]
1019 pub struct ECR {
1020 pub control: QubitId,
1022 pub target: QubitId,
1024 }
1025 impl GateOp for ECR {
1026 fn name(&self) -> &'static str {
1027 "ECR"
1028 }
1029 fn qubits(&self) -> Vec<QubitId> {
1030 vec![self.control, self.target]
1031 }
1032 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1033 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
1034 Ok(vec![
1035 Complex64::new(0.0, 0.0),
1036 Complex64::new(sqrt2_inv, 0.0),
1037 Complex64::new(0.0, 0.0),
1038 Complex64::new(0.0, sqrt2_inv),
1039 Complex64::new(sqrt2_inv, 0.0),
1040 Complex64::new(0.0, 0.0),
1041 Complex64::new(0.0, -sqrt2_inv),
1042 Complex64::new(0.0, 0.0),
1043 Complex64::new(0.0, 0.0),
1044 Complex64::new(0.0, sqrt2_inv),
1045 Complex64::new(0.0, 0.0),
1046 Complex64::new(sqrt2_inv, 0.0),
1047 Complex64::new(0.0, -sqrt2_inv),
1048 Complex64::new(0.0, 0.0),
1049 Complex64::new(sqrt2_inv, 0.0),
1050 Complex64::new(0.0, 0.0),
1051 ])
1052 }
1053 fn as_any(&self) -> &dyn Any {
1054 self
1055 }
1056 impl_clone_gate!();
1057 }
1058 #[derive(Debug, Clone, Copy)]
1062 pub struct RXX {
1063 pub qubit1: QubitId,
1065 pub qubit2: QubitId,
1067 pub theta: f64,
1069 }
1070 impl GateOp for RXX {
1071 fn name(&self) -> &'static str {
1072 "RXX"
1073 }
1074 fn qubits(&self) -> Vec<QubitId> {
1075 vec![self.qubit1, self.qubit2]
1076 }
1077 fn is_parameterized(&self) -> bool {
1078 true
1079 }
1080 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1081 let cos = (self.theta / 2.0).cos();
1082 let sin = (self.theta / 2.0).sin();
1083 let mi_sin = Complex64::new(0.0, -sin);
1084 Ok(vec![
1085 Complex64::new(cos, 0.0),
1086 Complex64::new(0.0, 0.0),
1087 Complex64::new(0.0, 0.0),
1088 mi_sin,
1089 Complex64::new(0.0, 0.0),
1090 Complex64::new(cos, 0.0),
1091 mi_sin,
1092 Complex64::new(0.0, 0.0),
1093 Complex64::new(0.0, 0.0),
1094 mi_sin,
1095 Complex64::new(cos, 0.0),
1096 Complex64::new(0.0, 0.0),
1097 mi_sin,
1098 Complex64::new(0.0, 0.0),
1099 Complex64::new(0.0, 0.0),
1100 Complex64::new(cos, 0.0),
1101 ])
1102 }
1103 fn as_any(&self) -> &dyn Any {
1104 self
1105 }
1106 impl_clone_gate!();
1107 }
1108 #[derive(Debug, Clone, Copy)]
1112 pub struct RYY {
1113 pub qubit1: QubitId,
1115 pub qubit2: QubitId,
1117 pub theta: f64,
1119 }
1120 impl GateOp for RYY {
1121 fn name(&self) -> &'static str {
1122 "RYY"
1123 }
1124 fn qubits(&self) -> Vec<QubitId> {
1125 vec![self.qubit1, self.qubit2]
1126 }
1127 fn is_parameterized(&self) -> bool {
1128 true
1129 }
1130 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1131 let cos = (self.theta / 2.0).cos();
1132 let sin = (self.theta / 2.0).sin();
1133 let i_sin = Complex64::new(0.0, sin);
1134 let mi_sin = Complex64::new(0.0, -sin);
1135 Ok(vec![
1136 Complex64::new(cos, 0.0),
1137 Complex64::new(0.0, 0.0),
1138 Complex64::new(0.0, 0.0),
1139 i_sin,
1140 Complex64::new(0.0, 0.0),
1141 Complex64::new(cos, 0.0),
1142 mi_sin,
1143 Complex64::new(0.0, 0.0),
1144 Complex64::new(0.0, 0.0),
1145 mi_sin,
1146 Complex64::new(cos, 0.0),
1147 Complex64::new(0.0, 0.0),
1148 i_sin,
1149 Complex64::new(0.0, 0.0),
1150 Complex64::new(0.0, 0.0),
1151 Complex64::new(cos, 0.0),
1152 ])
1153 }
1154 fn as_any(&self) -> &dyn Any {
1155 self
1156 }
1157 impl_clone_gate!();
1158 }
1159 #[derive(Debug, Clone, Copy)]
1163 pub struct RZZ {
1164 pub qubit1: QubitId,
1166 pub qubit2: QubitId,
1168 pub theta: f64,
1170 }
1171 impl GateOp for RZZ {
1172 fn name(&self) -> &'static str {
1173 "RZZ"
1174 }
1175 fn qubits(&self) -> Vec<QubitId> {
1176 vec![self.qubit1, self.qubit2]
1177 }
1178 fn is_parameterized(&self) -> bool {
1179 true
1180 }
1181 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1182 let phase_neg = Complex64::new(0.0, -self.theta / 2.0).exp();
1183 let phase_pos = Complex64::new(0.0, self.theta / 2.0).exp();
1184 Ok(vec![
1185 phase_neg,
1186 Complex64::new(0.0, 0.0),
1187 Complex64::new(0.0, 0.0),
1188 Complex64::new(0.0, 0.0),
1189 Complex64::new(0.0, 0.0),
1190 phase_pos,
1191 Complex64::new(0.0, 0.0),
1192 Complex64::new(0.0, 0.0),
1193 Complex64::new(0.0, 0.0),
1194 Complex64::new(0.0, 0.0),
1195 phase_pos,
1196 Complex64::new(0.0, 0.0),
1197 Complex64::new(0.0, 0.0),
1198 Complex64::new(0.0, 0.0),
1199 Complex64::new(0.0, 0.0),
1200 phase_neg,
1201 ])
1202 }
1203 fn as_any(&self) -> &dyn Any {
1204 self
1205 }
1206 impl_clone_gate!();
1207 }
1208 #[derive(Debug, Clone, Copy)]
1212 pub struct RZX {
1213 pub control: QubitId,
1215 pub target: QubitId,
1217 pub theta: f64,
1219 }
1220 impl GateOp for RZX {
1221 fn name(&self) -> &'static str {
1222 "RZX"
1223 }
1224 fn qubits(&self) -> Vec<QubitId> {
1225 vec![self.control, self.target]
1226 }
1227 fn is_parameterized(&self) -> bool {
1228 true
1229 }
1230 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1231 let cos = (self.theta / 2.0).cos();
1232 let sin = (self.theta / 2.0).sin();
1233 let mi_sin = Complex64::new(0.0, -sin);
1234 let i_sin = Complex64::new(0.0, sin);
1235 Ok(vec![
1236 Complex64::new(cos, 0.0),
1237 mi_sin,
1238 Complex64::new(0.0, 0.0),
1239 Complex64::new(0.0, 0.0),
1240 mi_sin,
1241 Complex64::new(cos, 0.0),
1242 Complex64::new(0.0, 0.0),
1243 Complex64::new(0.0, 0.0),
1244 Complex64::new(0.0, 0.0),
1245 Complex64::new(0.0, 0.0),
1246 Complex64::new(cos, 0.0),
1247 i_sin,
1248 Complex64::new(0.0, 0.0),
1249 Complex64::new(0.0, 0.0),
1250 i_sin,
1251 Complex64::new(cos, 0.0),
1252 ])
1253 }
1254 fn as_any(&self) -> &dyn Any {
1255 self
1256 }
1257 impl_clone_gate!();
1258 }
1259 #[derive(Debug, Clone, Copy)]
1263 pub struct DCX {
1264 pub qubit1: QubitId,
1266 pub qubit2: QubitId,
1268 }
1269 impl GateOp for DCX {
1270 fn name(&self) -> &'static str {
1271 "DCX"
1272 }
1273 fn qubits(&self) -> Vec<QubitId> {
1274 vec![self.qubit1, self.qubit2]
1275 }
1276 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1277 Ok(vec![
1278 Complex64::new(1.0, 0.0),
1279 Complex64::new(0.0, 0.0),
1280 Complex64::new(0.0, 0.0),
1281 Complex64::new(0.0, 0.0),
1282 Complex64::new(0.0, 0.0),
1283 Complex64::new(0.0, 0.0),
1284 Complex64::new(0.0, 0.0),
1285 Complex64::new(1.0, 0.0),
1286 Complex64::new(0.0, 0.0),
1287 Complex64::new(1.0, 0.0),
1288 Complex64::new(0.0, 0.0),
1289 Complex64::new(0.0, 0.0),
1290 Complex64::new(0.0, 0.0),
1291 Complex64::new(0.0, 0.0),
1292 Complex64::new(1.0, 0.0),
1293 Complex64::new(0.0, 0.0),
1294 ])
1295 }
1296 fn as_any(&self) -> &dyn Any {
1297 self
1298 }
1299 impl_clone_gate!();
1300 }
1301 #[derive(Debug, Clone, Copy)]
1305 pub struct XXPlusYY {
1306 pub qubit1: QubitId,
1308 pub qubit2: QubitId,
1310 pub theta: f64,
1312 pub beta: f64,
1314 }
1315 impl GateOp for XXPlusYY {
1316 fn name(&self) -> &'static str {
1317 "XXPlusYY"
1318 }
1319 fn qubits(&self) -> Vec<QubitId> {
1320 vec![self.qubit1, self.qubit2]
1321 }
1322 fn is_parameterized(&self) -> bool {
1323 true
1324 }
1325 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1326 let cos = (self.theta / 2.0).cos();
1327 let sin = (self.theta / 2.0).sin();
1328 let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
1329 let exp_i_beta = Complex64::new(0.0, self.beta).exp();
1330 let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
1331 let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
1332 Ok(vec![
1333 Complex64::new(1.0, 0.0),
1334 Complex64::new(0.0, 0.0),
1335 Complex64::new(0.0, 0.0),
1336 Complex64::new(0.0, 0.0),
1337 Complex64::new(0.0, 0.0),
1338 Complex64::new(cos, 0.0),
1339 mi_sin_neg,
1340 Complex64::new(0.0, 0.0),
1341 Complex64::new(0.0, 0.0),
1342 mi_sin_pos,
1343 Complex64::new(cos, 0.0),
1344 Complex64::new(0.0, 0.0),
1345 Complex64::new(0.0, 0.0),
1346 Complex64::new(0.0, 0.0),
1347 Complex64::new(0.0, 0.0),
1348 Complex64::new(1.0, 0.0),
1349 ])
1350 }
1351 fn as_any(&self) -> &dyn Any {
1352 self
1353 }
1354 impl_clone_gate!();
1355 }
1356 #[derive(Debug, Clone, Copy)]
1360 pub struct XXMinusYY {
1361 pub qubit1: QubitId,
1363 pub qubit2: QubitId,
1365 pub theta: f64,
1367 pub beta: f64,
1369 }
1370 impl GateOp for XXMinusYY {
1371 fn name(&self) -> &'static str {
1372 "XXMinusYY"
1373 }
1374 fn qubits(&self) -> Vec<QubitId> {
1375 vec![self.qubit1, self.qubit2]
1376 }
1377 fn is_parameterized(&self) -> bool {
1378 true
1379 }
1380 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1381 let cos = (self.theta / 2.0).cos();
1382 let sin = (self.theta / 2.0).sin();
1383 let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
1384 let exp_i_beta = Complex64::new(0.0, self.beta).exp();
1385 let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
1386 let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
1387 Ok(vec![
1388 Complex64::new(cos, 0.0),
1389 Complex64::new(0.0, 0.0),
1390 Complex64::new(0.0, 0.0),
1391 mi_sin_pos,
1392 Complex64::new(0.0, 0.0),
1393 Complex64::new(1.0, 0.0),
1394 Complex64::new(0.0, 0.0),
1395 Complex64::new(0.0, 0.0),
1396 Complex64::new(0.0, 0.0),
1397 Complex64::new(0.0, 0.0),
1398 Complex64::new(1.0, 0.0),
1399 Complex64::new(0.0, 0.0),
1400 mi_sin_neg,
1401 Complex64::new(0.0, 0.0),
1402 Complex64::new(0.0, 0.0),
1403 Complex64::new(cos, 0.0),
1404 ])
1405 }
1406 fn as_any(&self) -> &dyn Any {
1407 self
1408 }
1409 impl_clone_gate!();
1410 }
1411 #[derive(Debug, Clone, Copy)]
1413 pub struct CSX {
1414 pub control: QubitId,
1416 pub target: QubitId,
1418 }
1419 impl GateOp for CSX {
1420 fn name(&self) -> &'static str {
1421 "CSX"
1422 }
1423 fn qubits(&self) -> Vec<QubitId> {
1424 vec![self.control, self.target]
1425 }
1426 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1427 let half_plus_i_half = Complex64::new(0.5, 0.5);
1428 let half_minus_i_half = Complex64::new(0.5, -0.5);
1429 Ok(vec![
1430 Complex64::new(1.0, 0.0),
1431 Complex64::new(0.0, 0.0),
1432 Complex64::new(0.0, 0.0),
1433 Complex64::new(0.0, 0.0),
1434 Complex64::new(0.0, 0.0),
1435 Complex64::new(1.0, 0.0),
1436 Complex64::new(0.0, 0.0),
1437 Complex64::new(0.0, 0.0),
1438 Complex64::new(0.0, 0.0),
1439 Complex64::new(0.0, 0.0),
1440 half_plus_i_half,
1441 half_minus_i_half,
1442 Complex64::new(0.0, 0.0),
1443 Complex64::new(0.0, 0.0),
1444 half_minus_i_half,
1445 half_plus_i_half,
1446 ])
1447 }
1448 fn as_any(&self) -> &dyn Any {
1449 self
1450 }
1451 impl_clone_gate!();
1452 }
1453}
1454pub mod global {
1456 use super::*;
1457 #[derive(Debug, Clone, Copy)]
1461 pub struct GlobalPhase {
1462 pub phase: f64,
1464 }
1465 impl GateOp for GlobalPhase {
1466 fn name(&self) -> &'static str {
1467 "GlobalPhase"
1468 }
1469 fn qubits(&self) -> Vec<QubitId> {
1470 vec![]
1471 }
1472 fn is_parameterized(&self) -> bool {
1473 true
1474 }
1475 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1476 let phase = Complex64::new(0.0, self.phase).exp();
1477 Ok(vec![phase])
1478 }
1479 fn as_any(&self) -> &dyn Any {
1480 self
1481 }
1482 impl_clone_gate!();
1483 }
1484 #[derive(Debug, Clone, Copy)]
1488 pub struct RGate {
1489 pub target: QubitId,
1491 pub theta: f64,
1493 pub phi: f64,
1495 }
1496 impl GateOp for RGate {
1497 fn name(&self) -> &'static str {
1498 "R"
1499 }
1500 fn qubits(&self) -> Vec<QubitId> {
1501 vec![self.target]
1502 }
1503 fn is_parameterized(&self) -> bool {
1504 true
1505 }
1506 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1507 let cos = (self.theta / 2.0).cos();
1508 let sin = (self.theta / 2.0).sin();
1509 let exp_neg_i_phi = Complex64::new(0.0, -self.phi).exp();
1510 let exp_i_phi = Complex64::new(0.0, self.phi).exp();
1511 Ok(vec![
1512 Complex64::new(cos, 0.0),
1513 Complex64::new(0.0, -sin) * exp_neg_i_phi,
1514 Complex64::new(0.0, -sin) * exp_i_phi,
1515 Complex64::new(cos, 0.0),
1516 ])
1517 }
1518 fn as_any(&self) -> &dyn Any {
1519 self
1520 }
1521 impl_clone_gate!();
1522 }
1523}
1524
1525#[cfg(test)]
1526mod issue_32_rz_convention_tests {
1527 use super::multi::CRZ;
1528 use super::single::RotationZ;
1529 use super::GateOp;
1530 use crate::qubit::QubitId;
1531 use scirs2_core::Complex64;
1532 use std::f64::consts::PI;
1533
1534 #[test]
1540 fn test_issue_32_rotation_z_matrix_convention() {
1541 let theta = PI / 2.0;
1542 let m = RotationZ {
1543 target: QubitId::new(0),
1544 theta,
1545 }
1546 .matrix()
1547 .expect("RotationZ matrix");
1548
1549 let expected_00 = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
1551 let expected_11 = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
1553
1554 assert!((m[0] - expected_00).norm() < 1e-12, "m[0] = {:?}", m[0]);
1555 assert!(m[0].im < 0.0, "m[0] must have a negative imaginary part");
1556 assert_eq!(m[1], Complex64::new(0.0, 0.0));
1557 assert_eq!(m[2], Complex64::new(0.0, 0.0));
1558 assert!((m[3] - expected_11).norm() < 1e-12, "m[3] = {:?}", m[3]);
1559 assert!(m[3].im > 0.0, "m[3] must have a positive imaginary part");
1560 }
1561
1562 #[test]
1567 fn test_issue_32_crz_matrix_convention() {
1568 let theta = PI / 2.0;
1569 let m = CRZ {
1570 control: QubitId::new(0),
1571 target: QubitId::new(1),
1572 theta,
1573 }
1574 .matrix()
1575 .expect("CRZ matrix");
1576
1577 let expected_10 = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
1578 let expected_15 = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
1579
1580 assert_eq!(m[0], Complex64::new(1.0, 0.0));
1582 assert_eq!(m[1], Complex64::new(0.0, 0.0));
1583 assert_eq!(m[4], Complex64::new(0.0, 0.0));
1584 assert_eq!(m[5], Complex64::new(1.0, 0.0));
1585
1586 assert!((m[10] - expected_10).norm() < 1e-12, "m[10] = {:?}", m[10]);
1587 assert!(m[10].im < 0.0, "m[10] must have a negative imaginary part");
1588 assert!((m[15] - expected_15).norm() < 1e-12, "m[15] = {:?}", m[15]);
1589 assert!(m[15].im > 0.0, "m[15] must have a positive imaginary part");
1590 }
1591}