Skip to main content

quantrs2_core/gate/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use 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
12/// Macro to implement clone_gate method for gate types
13macro_rules! impl_clone_gate {
14    () => {
15        fn clone_gate(&self) -> Box<dyn GateOp> {
16            Box::new(self.clone())
17        }
18    };
19}
20/// Trait for quantum gate operations
21pub trait GateOp: Debug + Send + Sync {
22    /// Returns the name of the gate
23    fn name(&self) -> &'static str;
24    /// Returns the qubits that this gate acts on
25    fn qubits(&self) -> Vec<QubitId>;
26    /// Returns the number of qubits this gate acts on
27    fn num_qubits(&self) -> usize {
28        self.qubits().len()
29    }
30    /// Returns true if this gate is parameterized
31    fn is_parameterized(&self) -> bool {
32        false
33    }
34    /// Returns the matrix representation of this gate
35    fn matrix(&self) -> QuantRS2Result<Vec<Complex64>>;
36    /// Downcast to concrete gate type
37    fn as_any(&self) -> &dyn Any;
38    /// Clone the gate into a new boxed instance
39    fn clone_gate(&self) -> Box<dyn GateOp>;
40}
41/// Implement Clone for `Box<dyn GateOp>`
42impl Clone for Box<dyn GateOp> {
43    fn clone(&self) -> Self {
44        self.clone_gate()
45    }
46}
47/// Single-qubit gate operations
48pub mod single {
49    use super::*;
50    use super::*;
51    /// Hadamard gate
52    #[derive(Debug, Clone, Copy)]
53    pub struct Hadamard {
54        /// Target qubit
55        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    /// Pauli-X gate
79    #[derive(Debug, Clone, Copy)]
80    pub struct PauliX {
81        /// Target qubit
82        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    /// Pauli-Y gate
105    #[derive(Debug, Clone, Copy)]
106    pub struct PauliY {
107        /// Target qubit
108        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    /// Pauli-Z gate
131    #[derive(Debug, Clone, Copy)]
132    pub struct PauliZ {
133        /// Target qubit
134        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    /// Rotation around X-axis
157    #[derive(Debug, Clone, Copy)]
158    pub struct RotationX {
159        /// Target qubit
160        pub target: QubitId,
161        /// Rotation angle (in radians)
162        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    /// Rotation around Y-axis
190    #[derive(Debug, Clone, Copy)]
191    pub struct RotationY {
192        /// Target qubit
193        pub target: QubitId,
194        /// Rotation angle (in radians)
195        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    /// Rotation around Z-axis
223    #[derive(Debug, Clone, Copy)]
224    pub struct RotationZ {
225        /// Target qubit
226        pub target: QubitId,
227        /// Rotation angle (in radians)
228        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            // IBM/Qiskit/OpenQASM-3 convention: Rz(θ) = diag(e^{-iθ/2}, e^{+iθ/2})
244            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    /// Phase gate (S gate)
257    #[derive(Debug, Clone, Copy)]
258    pub struct Phase {
259        /// Target qubit
260        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    /// T gate
283    #[derive(Debug, Clone, Copy)]
284    pub struct T {
285        /// Target qubit
286        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    /// T-dagger gate (Conjugate of T gate)
310    #[derive(Debug, Clone, Copy)]
311    pub struct TDagger {
312        /// Target qubit
313        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    /// S-dagger gate (Conjugate of Phase/S gate)
337    #[derive(Debug, Clone, Copy)]
338    pub struct PhaseDagger {
339        /// Target qubit
340        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    /// Square Root of X (√X) gate
363    #[derive(Debug, Clone, Copy)]
364    pub struct SqrtX {
365        /// Target qubit
366        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    /// Square Root of X Dagger (√X†) gate
391    #[derive(Debug, Clone, Copy)]
392    pub struct SqrtXDagger {
393        /// Target qubit
394        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    /// U gate - General single-qubit rotation (Qiskit compatible)
419    ///
420    /// U(θ, φ, λ) = [[cos(θ/2), -e^(iλ)·sin(θ/2)],
421    ///              [e^(iφ)·sin(θ/2), e^(i(φ+λ))·cos(θ/2)]]
422    #[derive(Debug, Clone, Copy)]
423    pub struct UGate {
424        /// Target qubit
425        pub target: QubitId,
426        /// Rotation angle theta
427        pub theta: f64,
428        /// Phase angle phi
429        pub phi: f64,
430        /// Phase angle lambda
431        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    /// P gate - Phase gate with parameter (equivalent to RZ up to global phase)
462    ///
463    /// P(λ) = [[1, 0], [0, e^(iλ)]]
464    #[derive(Debug, Clone, Copy)]
465    pub struct PGate {
466        /// Target qubit
467        pub target: QubitId,
468        /// Phase angle lambda
469        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    /// Identity gate
496    #[derive(Debug, Clone, Copy)]
497    pub struct Identity {
498        /// Target qubit
499        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}
522/// Multi-qubit gate operations
523pub mod multi {
524    use super::*;
525    /// Controlled-NOT gate
526    #[derive(Debug, Clone, Copy)]
527    pub struct CNOT {
528        /// Control qubit
529        pub control: QubitId,
530        /// Target qubit
531        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    /// Controlled-Z gate
566    #[derive(Debug, Clone, Copy)]
567    pub struct CZ {
568        /// Control qubit
569        pub control: QubitId,
570        /// Target qubit
571        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    /// SWAP gate
606    #[derive(Debug, Clone, Copy)]
607    pub struct SWAP {
608        /// First qubit
609        pub qubit1: QubitId,
610        /// Second qubit
611        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    /// Controlled-Y (CY) gate
646    #[derive(Debug, Clone, Copy)]
647    pub struct CY {
648        /// Control qubit
649        pub control: QubitId,
650        /// Target qubit
651        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    /// Controlled-H (CH) gate
686    #[derive(Debug, Clone, Copy)]
687    pub struct CH {
688        /// Control qubit
689        pub control: QubitId,
690        /// Target qubit
691        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    /// Controlled-Phase (CS) gate
727    #[derive(Debug, Clone, Copy)]
728    pub struct CS {
729        /// Control qubit
730        pub control: QubitId,
731        /// Target qubit
732        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    /// Toffoli (CCNOT) gate
767    #[derive(Debug, Clone, Copy)]
768    pub struct Toffoli {
769        /// First control qubit
770        pub control1: QubitId,
771        /// Second control qubit
772        pub control2: QubitId,
773        /// Target qubit
774        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    /// Fredkin (CSWAP) gate
796    #[derive(Debug, Clone, Copy)]
797    pub struct Fredkin {
798        /// Control qubit
799        pub control: QubitId,
800        /// First target qubit
801        pub target1: QubitId,
802        /// Second target qubit
803        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    /// Controlled Rotation-X gate (CRX)
825    #[derive(Debug, Clone, Copy)]
826    pub struct CRX {
827        /// Control qubit
828        pub control: QubitId,
829        /// Target qubit
830        pub target: QubitId,
831        /// Rotation angle (in radians)
832        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    /// Controlled Rotation-Y gate (CRY)
872    #[derive(Debug, Clone, Copy)]
873    pub struct CRY {
874        /// Control qubit
875        pub control: QubitId,
876        /// Target qubit
877        pub target: QubitId,
878        /// Rotation angle (in radians)
879        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    /// Controlled Rotation-Z gate (CRZ)
919    #[derive(Debug, Clone, Copy)]
920    pub struct CRZ {
921        /// Control qubit
922        pub control: QubitId,
923        /// Target qubit
924        pub target: QubitId,
925        /// Rotation angle (in radians)
926        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            // Controlled Rz in the IBM/Qiskit/OpenQASM-3 convention: the target
942            // block is Rz(θ) = diag(e^{-iθ/2}, e^{+iθ/2}) when the control is |1⟩.
943            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    /// iSWAP gate - swaps two qubits and phases |01⟩ and |10⟩ by i
968    ///
969    /// iSWAP = [[1, 0, 0, 0],
970    ///          [0, 0, i, 0],
971    ///          [0, i, 0, 0],
972    ///          [0, 0, 0, 1]]
973    #[derive(Debug, Clone, Copy)]
974    pub struct ISwap {
975        /// First qubit
976        pub qubit1: QubitId,
977        /// Second qubit
978        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    /// ECR gate - Echoed Cross-Resonance gate (IBM native two-qubit gate)
1013    ///
1014    /// ECR = (1/√2) * [[0, 1, 0, i],
1015    ///                  [1, 0, -i, 0],
1016    ///                  [0, i, 0, 1],
1017    ///                  [-i, 0, 1, 0]]
1018    #[derive(Debug, Clone, Copy)]
1019    pub struct ECR {
1020        /// Control qubit
1021        pub control: QubitId,
1022        /// Target qubit
1023        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    /// RXX gate - Two-qubit XX rotation
1059    ///
1060    /// RXX(θ) = exp(-i * θ/2 * X⊗X)
1061    #[derive(Debug, Clone, Copy)]
1062    pub struct RXX {
1063        /// First qubit
1064        pub qubit1: QubitId,
1065        /// Second qubit
1066        pub qubit2: QubitId,
1067        /// Rotation angle
1068        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    /// RYY gate - Two-qubit YY rotation
1109    ///
1110    /// RYY(θ) = exp(-i * θ/2 * Y⊗Y)
1111    #[derive(Debug, Clone, Copy)]
1112    pub struct RYY {
1113        /// First qubit
1114        pub qubit1: QubitId,
1115        /// Second qubit
1116        pub qubit2: QubitId,
1117        /// Rotation angle
1118        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    /// RZZ gate - Two-qubit ZZ rotation
1160    ///
1161    /// RZZ(θ) = exp(-i * θ/2 * Z⊗Z)
1162    #[derive(Debug, Clone, Copy)]
1163    pub struct RZZ {
1164        /// First qubit
1165        pub qubit1: QubitId,
1166        /// Second qubit
1167        pub qubit2: QubitId,
1168        /// Rotation angle
1169        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    /// RZX gate - Two-qubit ZX rotation (Cross-resonance gate)
1209    ///
1210    /// RZX(θ) = exp(-i * θ/2 * Z⊗X)
1211    #[derive(Debug, Clone, Copy)]
1212    pub struct RZX {
1213        /// Control qubit (Z)
1214        pub control: QubitId,
1215        /// Target qubit (X)
1216        pub target: QubitId,
1217        /// Rotation angle
1218        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    /// DCX gate - Double CNOT gate
1260    ///
1261    /// DCX = CNOT(0,1) @ CNOT(1,0)
1262    #[derive(Debug, Clone, Copy)]
1263    pub struct DCX {
1264        /// First qubit
1265        pub qubit1: QubitId,
1266        /// Second qubit
1267        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    /// XXPlusYY gate - Two-qubit XX+YY interaction (XY gate)
1302    ///
1303    /// Induces a coherent rotation between |01⟩ and |10⟩
1304    #[derive(Debug, Clone, Copy)]
1305    pub struct XXPlusYY {
1306        /// First qubit
1307        pub qubit1: QubitId,
1308        /// Second qubit
1309        pub qubit2: QubitId,
1310        /// Rotation angle theta
1311        pub theta: f64,
1312        /// Phase angle beta
1313        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    /// XXMinusYY gate - Two-qubit XX-YY interaction
1357    ///
1358    /// Induces a coherent rotation between |00⟩ and |11⟩
1359    #[derive(Debug, Clone, Copy)]
1360    pub struct XXMinusYY {
1361        /// First qubit
1362        pub qubit1: QubitId,
1363        /// Second qubit
1364        pub qubit2: QubitId,
1365        /// Rotation angle theta
1366        pub theta: f64,
1367        /// Phase angle beta
1368        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    /// CSX gate - Controlled-√X gate
1412    #[derive(Debug, Clone, Copy)]
1413    pub struct CSX {
1414        /// Control qubit
1415        pub control: QubitId,
1416        /// Target qubit
1417        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}
1454/// Global phase and other zero-qubit gates
1455pub mod global {
1456    use super::*;
1457    /// Global Phase gate - applies a global phase to the quantum state
1458    ///
1459    /// GlobalPhase(θ) = e^(iθ) * I
1460    #[derive(Debug, Clone, Copy)]
1461    pub struct GlobalPhase {
1462        /// Phase angle
1463        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    /// R gate - Rotation around axis in X-Y plane
1485    ///
1486    /// R(θ, φ) = exp(-i * θ/2 * (cos(φ)X + sin(φ)Y))
1487    #[derive(Debug, Clone, Copy)]
1488    pub struct RGate {
1489        /// Target qubit
1490        pub target: QubitId,
1491        /// Rotation angle theta
1492        pub theta: f64,
1493        /// Axis angle phi
1494        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    /// Regression test for GitHub issue #32.
1535    ///
1536    /// `RotationZ` must follow the IBM/Qiskit/OpenQASM-3 convention
1537    /// `Rz(θ) = diag(e^{-iθ/2}, e^{+iθ/2})`: for θ = π/2 the top-left diagonal
1538    /// entry carries a negative imaginary part and the bottom-right a positive one.
1539    #[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        // Hand-computed: e^{-iπ/4} = cos(π/4) - i·sin(π/4)
1550        let expected_00 = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
1551        // e^{+iπ/4} = cos(π/4) + i·sin(π/4)
1552        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    /// Regression test for GitHub issue #32.
1563    ///
1564    /// `CRZ` must apply `Rz(θ) = diag(e^{-iθ/2}, e^{+iθ/2})` on the target when the
1565    /// control is |1⟩ (flat indices 10 and 15), with an identity top-left 2×2 block.
1566    #[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        // Top-left 2x2 block is the identity (control |0⟩ leaves the target unchanged).
1581        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}