LCOV - code coverage report
Current view: top level - src/operations - single_qubit_gate_operations.rs (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 496 496 100.0 %
Date: 2021-11-09 13:25:48 Functions: 314 314 100.0 %

          Line data    Source code
       1             : // Copyright © 2021 HQS Quantum Simulations GmbH. All Rights Reserved.
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
       4             : // in compliance with the License. You may obtain a copy of the License at
       5             : //
       6             : //     http://www.apache.org/licenses/LICENSE-2.0
       7             : //
       8             : // Unless required by applicable law or agreed to in writing, software distributed under the
       9             : // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      10             : // express or implied. See the License for the specific language governing permissions and
      11             : // limitations under the License.
      12             : 
      13             : use ndarray::{array, Array2};
      14             : use num_complex::Complex64;
      15             : use qoqo_calculator::CalculatorFloat;
      16             : use std::convert::TryFrom;
      17             : use std::f64::consts::PI;
      18             : 
      19             : use crate::operations::{
      20             :     InvolveQubits, InvolvedQubits, Operate, OperateGate, OperateSingleQubit,
      21             :     OperateSingleQubitGate, Rotate, Substitute,
      22             : };
      23             : use crate::RoqoqoError;
      24             : #[cfg(feature = "overrotate")]
      25             : use rand_distr::{Distribution, Normal};
      26             : 
      27             : /// The most general unitary operation acting on one qubit.
      28             : ///
      29             : /// $$ U =e^{i \phi}\begin{pmatrix}
      30             : /// \alpha_r+i \alpha_i & -\beta_r+i \beta_i \\\\
      31             : /// \beta_r+i \beta_i & \alpha_r-i\alpha_i
      32             : /// \end{pmatrix} $$
      33             : ///
      34             : /// # Warning
      35             : ///
      36             : /// Due to the support of parameterized values it cannot be guaranteed that the unitary matrix of the gate
      37             : /// is always normalized to one.
      38             : ///
      39             : #[derive(
      40           1 :     Debug,
      41          45 :     Clone,
      42          12 :     PartialEq,
      43           9 :     roqoqo_derive::InvolveQubits,
      44           2 :     roqoqo_derive::Operate,
      45           9 :     roqoqo_derive::Substitute,
      46          78 :     roqoqo_derive::OperateSingleQubit,
      47             : )]
      48             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
      49             : pub struct SingleQubitGate {
      50             :     /// The qubit the unitary gate is applied to.
      51             :     qubit: usize,
      52             :     /// The real part $ \alpha_r $ of the on-diagonal elements of the single-qubit unitary.
      53             :     alpha_r: CalculatorFloat,
      54             :     /// The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary.
      55             :     alpha_i: CalculatorFloat,
      56             :     /// The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary.
      57             :     beta_r: CalculatorFloat,
      58             :     /// The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary.
      59             :     beta_i: CalculatorFloat,
      60             :     /// The global phase $ \phi $ of the single-qubit unitary.
      61             :     global_phase: CalculatorFloat,
      62             : }
      63             : 
      64             : #[allow(non_upper_case_globals)]
      65             : const TAGS_SingleQubitGate: &[&str; 4] = &[
      66             :     "Operation",
      67             :     "GateOperation",
      68             :     "SingleQubitGateOperation",
      69             :     "SingleQubitGate",
      70             : ];
      71             : 
      72             : /// Trait for all operations acting with a unitary gate on a set of qubits.
      73             : impl OperateGate for SingleQubitGate {
      74             :     /// Returns unitary matrix of the gate.
      75             :     ///
      76             :     /// # Returns
      77             :     ///
      78             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
      79             :     /// * `Err(RoqoqoError)` - The conversion of parameters to f64 failed or matrix normalization failed.
      80         118 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
      81         118 :         let alpha_r: f64 = f64::try_from(self.alpha_r())?;
      82         117 :         let alpha_i: f64 = f64::try_from(self.alpha_i())?;
      83         117 :         let beta_r: f64 = f64::try_from(self.beta_r())?;
      84         117 :         let beta_i: f64 = f64::try_from(self.beta_i())?;
      85         117 :         let global_phase: f64 = f64::try_from(self.global_phase())?;
      86             :         // before building the unitary matrix, check values of alpha and beta for the matrix to be normalized.
      87         117 :         if alpha_r == 0.0 && alpha_i == 0.0 && beta_r == 0.0 && beta_i == 0.0
      88         116 :             || (alpha_r.powf(2.0) + alpha_i.powf(2.0) + beta_r.powf(2.0) + beta_i.powf(2.0) - 1.0)
      89         116 :                 .abs()
      90         116 :                 > f64::EPSILON
      91             :         {
      92           2 :             let norm: f64 =
      93           2 :                 alpha_r.powf(2.0) + alpha_i.powf(2.0) + beta_r.powf(2.0) + beta_i.powf(2.0);
      94           2 :             Err(RoqoqoError::UnitaryMatrixErrror {
      95           2 :                 alpha_r,
      96           2 :                 alpha_i,
      97           2 :                 beta_r,
      98           2 :                 beta_i,
      99           2 :                 norm,
     100           2 :             })
     101             :         } else {
     102         116 :             let pref = Complex64::new(0.0, global_phase).exp();
     103         116 :             Ok(array![
     104         116 :                 [
     105         116 :                     pref * Complex64::new(alpha_r, alpha_i),
     106         116 :                     pref * Complex64::new(-1.0 * beta_r, beta_i)
     107         116 :                 ],
     108         116 :                 [
     109         116 :                     pref * Complex64::new(beta_r, beta_i),
     110         116 :                     pref * Complex64::new(alpha_r, -1.0 * alpha_i)
     111         116 :                 ]
     112         116 :             ])
     113             :         }
     114         119 :     }
     115             : }
     116             : 
     117             : /// Trait for unitary operations acting on exactly one qubit.
     118             : impl OperateSingleQubitGate for SingleQubitGate {
     119             :     /// Returns the alpha_r parameter of the operation.
     120             :     ///
     121             :     /// # Returns
     122             :     ///
     123             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     124         168 :     fn alpha_r(&self) -> CalculatorFloat {
     125         168 :         self.alpha_r.clone()
     126         168 :     }
     127             :     /// Returns the alpha_i parameter of the operation.
     128             :     ///
     129             :     /// # Returns
     130             :     ///
     131             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     132         166 :     fn alpha_i(&self) -> CalculatorFloat {
     133         166 :         self.alpha_i.clone()
     134         166 :     }
     135             :     /// Returns the beta_r parameter of the operation.
     136             :     ///
     137             :     /// # Returns
     138             :     ///
     139             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     140         168 :     fn beta_r(&self) -> CalculatorFloat {
     141         168 :         self.beta_r.clone()
     142         168 :     }
     143             :     /// Returns the beta_i parameter of the operation.
     144             :     ///
     145             :     /// # Returns
     146             :     ///
     147             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     148         167 :     fn beta_i(&self) -> CalculatorFloat {
     149         167 :         self.beta_i.clone()
     150         167 :     }
     151             :     /// Returns global_phase parameter of the operation.
     152             :     ///
     153             :     /// # Returns
     154             :     ///
     155             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     156         164 :     fn global_phase(&self) -> CalculatorFloat {
     157         164 :         self.global_phase.clone()
     158         164 :     }
     159             : }
     160             : 
     161             : /// The ZPower gate $e^{-i \frac{\theta}{2} \sigma^z}$.
     162             : ///
     163             : /// $$
     164             : /// U = \begin{pmatrix}
     165             : /// \cos(\frac{\theta}{2}) & 0\\\\
     166             : /// 0 & \cos(\frac{\theta}{2})
     167             : /// \end{pmatrix}
     168             : ///  + \begin{pmatrix}
     169             : ///  -i \sin(\frac{\theta}{2}) & 0\\\\
     170             : /// 0 & i \sin(\frac{\theta}{2})
     171             : /// \end{pmatrix}
     172             : /// $$
     173             : ///
     174             : #[derive(
     175           1 :     Debug,
     176         180 :     Clone,
     177          55 :     PartialEq,
     178           9 :     roqoqo_derive::InvolveQubits,
     179         267 :     roqoqo_derive::Operate,
     180          21 :     roqoqo_derive::Substitute,
     181          70 :     roqoqo_derive::OperateSingleQubit,
     182          14 :     roqoqo_derive::Rotate,
     183             : )]
     184             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     185             : pub struct RotateZ {
     186             :     /// The qubit the unitary gate is applied to.
     187             :     qubit: usize,
     188             :     /// The angle $\theta$ of the rotation, in the interval from 0 to $2^* 2 \pi$.
     189             :     theta: CalculatorFloat,
     190             : }
     191             : 
     192             : #[allow(non_upper_case_globals)]
     193             : const TAGS_RotateZ: &[&str; 5] = &[
     194             :     "Operation",
     195             :     "GateOperation",
     196             :     "SingleQubitGateOperation",
     197             :     "Rotation",
     198             :     "RotateZ",
     199             : ];
     200             : 
     201             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     202             : impl OperateGate for RotateZ {
     203             :     /// Returns unitary matrix of the gate.
     204             :     ///
     205             :     /// # Returns
     206             :     ///
     207             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     208             :     /// * `Err(RoqoqoError)` - The conversion of theta to f64 failed.
     209           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     210           2 :         let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
     211           2 :         let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
     212           2 :         Ok(array![
     213           2 :             [Complex64::new(c, -1.0 * s), Complex64::new(0.0, 0.0)],
     214           2 :             [Complex64::new(0.0, 0.0), Complex64::new(c, s)]
     215           2 :         ])
     216           2 :     }
     217             : }
     218             : 
     219             : /// Trait for unitary operations acting on exactly one qubit.
     220             : impl OperateSingleQubitGate for RotateZ {
     221             :     /// Returns the alpha_r parameter of the operation.
     222             :     ///
     223             :     /// # Returns
     224             :     ///
     225             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     226          43 :     fn alpha_r(&self) -> CalculatorFloat {
     227          43 :         (self.theta.clone() / 2.0).cos()
     228          43 :     }
     229             : 
     230             :     /// Returns the alpha_i parameter of the operation.
     231             :     ///
     232             :     /// # Returns
     233             :     ///
     234             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     235          43 :     fn alpha_i(&self) -> CalculatorFloat {
     236          43 :         (self.theta.clone() / 2.0).sin() * (-1.0)
     237          43 :     }
     238             : 
     239             :     /// Returns the beta_r parameter of the operation.
     240             :     ///
     241             :     /// # Returns
     242             :     ///
     243             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     244          40 :     fn beta_r(&self) -> CalculatorFloat {
     245          40 :         CalculatorFloat::from(0.0)
     246          40 :     }
     247             : 
     248             :     /// Returns the beta_i parameter of the operation.
     249             :     ///
     250             :     /// # Returns
     251             :     ///
     252             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     253          40 :     fn beta_i(&self) -> CalculatorFloat {
     254          40 :         CalculatorFloat::from(0.0)
     255          40 :     }
     256             : 
     257             :     /// Returns global_phase parameter of the operation.
     258             :     ///
     259             :     /// # Returns
     260             :     ///
     261             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     262          39 :     fn global_phase(&self) -> CalculatorFloat {
     263          39 :         CalculatorFloat::from(0.0)
     264          39 :     }
     265             : }
     266             : 
     267             : /// The XPower gate $e^{-i \frac{\theta}{2} \sigma^x}$.
     268             : ///
     269             : /// $$
     270             : /// U = \begin{pmatrix}
     271             : /// \cos(\frac{\theta}{2}) & 0\\\\
     272             : /// 0 & \cos(\frac{\theta}{2})
     273             : /// \end{pmatrix}
     274             : /// + \begin{pmatrix}
     275             : /// 0  &  -i \sin(\frac{\theta}{2})   \\\\
     276             : /// -i \sin(\frac{\theta}{2})  & 0
     277             : /// \end{pmatrix}
     278             : ///  $$
     279             : ///
     280             : #[derive(
     281           5 :     Debug,
     282          74 :     Clone,
     283          41 :     PartialEq,
     284          10 :     roqoqo_derive::InvolveQubits,
     285         164 :     roqoqo_derive::Operate,
     286          19 :     roqoqo_derive::Substitute,
     287          23 :     roqoqo_derive::OperateSingleQubit,
     288          26 :     roqoqo_derive::Rotate,
     289             : )]
     290             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     291             : pub struct RotateX {
     292             :     /// The qubit the unitary gate is applied to.
     293             :     qubit: usize,
     294             :     /// The angle $\theta$ of the rotation, in the interval from 0 to $2^* 2 \pi$.
     295             :     theta: CalculatorFloat,
     296             : }
     297             : #[allow(non_upper_case_globals)]
     298             : const TAGS_RotateX: &[&str; 5] = &[
     299             :     "Operation",
     300             :     "GateOperation",
     301             :     "SingleQubitGateOperation",
     302             :     "Rotation",
     303             :     "RotateX",
     304             : ];
     305             : 
     306             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     307             : impl OperateGate for RotateX {
     308             :     /// Returns unitary matrix of the gate.
     309             :     ///
     310             :     /// # Returns
     311             :     ///
     312             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     313             :     /// * `Err(RoqoqoError)` - The conversion of theta to f64 failed.
     314           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     315           2 :         let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
     316           2 :         let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
     317           2 :         Ok(array![
     318           2 :             [Complex64::new(c, 0.0), Complex64::new(0.0, -1.0 * s)],
     319           2 :             [Complex64::new(0.0, -1.0 * s), Complex64::new(c, 0.0)]
     320           2 :         ])
     321           2 :     }
     322             : }
     323             : 
     324             : /// Trait for unitary operations acting on exactly one qubit.
     325             : impl OperateSingleQubitGate for RotateX {
     326             :     /// Returns the alpha_r parameter of the operation.
     327             :     ///
     328             :     /// # Returns
     329             :     ///
     330             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     331          29 :     fn alpha_r(&self) -> CalculatorFloat {
     332          29 :         (self.theta.clone() / 2.0).cos()
     333          29 :     }
     334             :     /// Returns the alpha_i parameter of the operation.
     335             :     ///
     336             :     /// # Returns
     337             :     ///
     338             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     339          26 :     fn alpha_i(&self) -> CalculatorFloat {
     340          26 :         CalculatorFloat::from(0.0)
     341          26 :     }
     342             :     /// Returns the beta_r parameter of the operation.
     343             :     ///
     344             :     /// # Returns
     345             :     ///
     346             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     347          26 :     fn beta_r(&self) -> CalculatorFloat {
     348          26 :         CalculatorFloat::from(0.0)
     349          26 :     }
     350             :     /// Returns the beta_i parameter of the operation.
     351             :     ///
     352             :     /// # Returns
     353             :     ///
     354             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     355          29 :     fn beta_i(&self) -> CalculatorFloat {
     356          29 :         (self.theta.clone() / 2.0).sin() * (-1.0)
     357          29 :     }
     358             :     /// Returns global_phase parameter of the operation.
     359             :     ///
     360             :     /// # Returns
     361             :     ///
     362             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     363          26 :     fn global_phase(&self) -> CalculatorFloat {
     364          26 :         CalculatorFloat::from(0.0)
     365          26 :     }
     366             : }
     367             : 
     368             : /// The YPower gate $e^{-i \frac{\theta}{2} \sigma^y}$.
     369             : ///
     370             : /// $$
     371             : /// U = \begin{pmatrix}
     372             : /// \cos(\frac{\theta}{2}) & 0\\\\
     373             : /// 0 & \cos(\frac{\theta}{2})
     374             : /// \end{pmatrix}
     375             : /// + \begin{pmatrix}
     376             : /// 0 & - \sin(\frac{\theta}{2})\\\\
     377             : /// \sin(\frac{\theta}{2}) & 0
     378             : /// \end{pmatrix}
     379             : ///  $$
     380             : ///
     381             : #[derive(
     382           1 :     Debug,
     383          33 :     Clone,
     384          18 :     PartialEq,
     385           9 :     roqoqo_derive::InvolveQubits,
     386          64 :     roqoqo_derive::Operate,
     387           9 :     roqoqo_derive::Substitute,
     388          19 :     roqoqo_derive::OperateSingleQubit,
     389          14 :     roqoqo_derive::Rotate,
     390             : )]
     391             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     392             : pub struct RotateY {
     393             :     /// The qubit the unitary gate is applied to.
     394             :     qubit: usize,
     395             :     /// The angle $\theta$ of the rotation, in the interval from 0 to $2^* 2 \pi$.
     396             :     theta: CalculatorFloat,
     397             : }
     398             : #[allow(non_upper_case_globals)]
     399             : const TAGS_RotateY: &[&str; 5] = &[
     400             :     "Operation",
     401             :     "GateOperation",
     402             :     "SingleQubitGateOperation",
     403             :     "Rotation",
     404             :     "RotateY",
     405             : ];
     406             : 
     407             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     408             : impl OperateGate for RotateY {
     409             :     /// Returns unitary matrix of the gate.
     410             :     ///
     411             :     /// # Returns
     412             :     ///
     413             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     414             :     /// * `Err(RoqoqoError)` - The conversion of theta to f64 failed.
     415           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     416           2 :         let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
     417           2 :         let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
     418           2 :         Ok(array![
     419           2 :             [Complex64::new(c, 0.0), Complex64::new(-1.0 * s, 0.0)],
     420           2 :             [Complex64::new(s, 0.0), Complex64::new(c, 0.0)]
     421           2 :         ])
     422           2 :     }
     423             : }
     424             : 
     425             : /// Trait for unitary operations acting on exactly one qubit.
     426             : impl OperateSingleQubitGate for RotateY {
     427             :     /// Returns the alpha_r parameter of the operation.
     428             :     ///
     429             :     /// # Returns
     430             :     ///
     431             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     432          14 :     fn alpha_r(&self) -> CalculatorFloat {
     433          14 :         (self.theta.clone() / 2.0).cos()
     434          14 :     }
     435             :     /// Returns the alpha_i parameter of the operation.
     436             :     ///
     437             :     /// # Returns
     438             :     ///
     439             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     440          11 :     fn alpha_i(&self) -> CalculatorFloat {
     441          11 :         CalculatorFloat::from(0.0)
     442          11 :     }
     443             :     /// Returns the beta_r parameter of the operation.
     444             :     ///
     445             :     /// # Returns
     446             :     ///
     447             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     448          14 :     fn beta_r(&self) -> CalculatorFloat {
     449          14 :         (self.theta.clone() / 2.0).sin()
     450          14 :     }
     451             :     /// Returns the beta_i parameter of the operation.
     452             :     ///
     453             :     /// # Returns
     454             :     ///
     455             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     456          11 :     fn beta_i(&self) -> CalculatorFloat {
     457          11 :         CalculatorFloat::from(0.0)
     458          11 :     }
     459             :     /// Returns global_phase parameter of the operation.
     460             :     ///
     461             :     /// # Returns
     462             :     ///
     463             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     464          11 :     fn global_phase(&self) -> CalculatorFloat {
     465          11 :         CalculatorFloat::from(0.0)
     466          11 :     }
     467             : }
     468             : 
     469             : /// The Pauli X gate.
     470             : ///
     471             : /// $$
     472             : /// U = \begin{pmatrix}
     473             : /// 0 & 1\\\\
     474             : /// 1 & 0
     475             : /// \end{pmatrix}
     476             : /// $$
     477             : ///
     478             : #[derive(
     479           2 :     Debug,
     480          24 :     Clone,
     481          22 :     PartialEq,
     482           5 :     roqoqo_derive::InvolveQubits,
     483          53 :     roqoqo_derive::Operate,
     484           9 :     roqoqo_derive::Substitute,
     485          11 :     roqoqo_derive::OperateSingleQubit,
     486             : )]
     487             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     488             : pub struct PauliX {
     489             :     /// The qubit the unitary gate is applied to.
     490             :     qubit: usize,
     491             : }
     492             : 
     493             : #[allow(non_upper_case_globals)]
     494             : const TAGS_PauliX: &[&str; 4] = &[
     495             :     "Operation",
     496             :     "GateOperation",
     497             :     "SingleQubitGateOperation",
     498             :     "PauliX",
     499             : ];
     500             : 
     501             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     502             : impl OperateGate for PauliX {
     503             :     /// Returns unitary matrix of the gate.
     504             :     ///
     505             :     /// # Returns
     506             :     ///
     507             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     508             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
     509           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     510           2 :         Ok(array![
     511           2 :             [Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0)],
     512           2 :             [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)]
     513           2 :         ])
     514           2 :     }
     515             : }
     516             : 
     517             : /// Trait for unitary operations acting on exactly one qubit.
     518             : impl OperateSingleQubitGate for PauliX {
     519             :     /// Returns the alpha_r parameter of the operation.
     520             :     ///
     521             :     /// # Returns
     522             :     ///
     523             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     524           5 :     fn alpha_r(&self) -> CalculatorFloat {
     525           5 :         CalculatorFloat::from(0.0)
     526           5 :     }
     527             :     /// Returns the alpha_i parameter of the operation.
     528             :     ///
     529             :     /// # Returns
     530             :     ///
     531             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     532           5 :     fn alpha_i(&self) -> CalculatorFloat {
     533           5 :         CalculatorFloat::from(0.0)
     534           5 :     }
     535             :     /// Returns the beta_r parameter of the operation.
     536             :     ///
     537             :     /// # Returns
     538             :     ///
     539             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     540           5 :     fn beta_r(&self) -> CalculatorFloat {
     541           5 :         CalculatorFloat::from(0.0)
     542           5 :     }
     543             :     /// Returns the beta_i parameter of the operation.
     544             :     ///
     545             :     /// # Returns
     546             :     ///
     547             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     548           5 :     fn beta_i(&self) -> CalculatorFloat {
     549           5 :         CalculatorFloat::from(-1.0)
     550           5 :     }
     551             :     /// Returns global_phase parameter of the operation.
     552             :     ///
     553             :     /// # Returns
     554             :     ///
     555             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     556           5 :     fn global_phase(&self) -> CalculatorFloat {
     557           5 :         CalculatorFloat::from((PI) / 2.0)
     558           5 :     }
     559             : }
     560             : 
     561             : /// The Pauli Y gate.
     562             : ///
     563             : /// $$
     564             : /// U = \begin{pmatrix}
     565             : /// 0 & -i\\\\
     566             : /// i & 0
     567             : /// \end{pmatrix}
     568             : /// $$
     569             : ///
     570             : #[derive(
     571           1 :     Debug,
     572           8 :     Clone,
     573           8 :     PartialEq,
     574           3 :     roqoqo_derive::InvolveQubits,
     575          29 :     roqoqo_derive::Operate,
     576           3 :     roqoqo_derive::Substitute,
     577          11 :     roqoqo_derive::OperateSingleQubit,
     578             : )]
     579             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     580             : pub struct PauliY {
     581             :     /// The qubit the unitary gate is applied to.
     582             :     qubit: usize,
     583             : }
     584             : 
     585             : #[allow(non_upper_case_globals)]
     586             : const TAGS_PauliY: &[&str; 4] = &[
     587             :     "Operation",
     588             :     "GateOperation",
     589             :     "SingleQubitGateOperation",
     590             :     "PauliY",
     591             : ];
     592             : 
     593             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     594             : impl OperateGate for PauliY {
     595             :     /// Returns unitary matrix of the gate.
     596             :     ///
     597             :     /// # Returns
     598             :     ///
     599             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     600             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
     601           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     602           2 :         Ok(array![
     603           2 :             [Complex64::new(0.0, 0.0), Complex64::new(0.0, -1.0)],
     604           2 :             [Complex64::new(0.0, 1.0), Complex64::new(0.0, 0.0)]
     605           2 :         ])
     606           2 :     }
     607             : }
     608             : 
     609             : /// Trait for unitary operations acting on exactly one qubit.
     610             : impl OperateSingleQubitGate for PauliY {
     611             :     /// Returns the alpha_r parameter of the operation.
     612             :     ///
     613             :     /// # Returns
     614             :     ///
     615             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     616           5 :     fn alpha_r(&self) -> CalculatorFloat {
     617           5 :         CalculatorFloat::from(0.0)
     618           5 :     }
     619             :     /// Returns the alpha_i parameter of the operation.
     620             :     ///
     621             :     /// # Returns
     622             :     ///
     623             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     624           5 :     fn alpha_i(&self) -> CalculatorFloat {
     625           5 :         CalculatorFloat::from(0.0)
     626           5 :     }
     627             :     /// Returns the beta_r parameter of the operation.
     628             :     ///
     629             :     /// # Returns
     630             :     ///
     631             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     632           5 :     fn beta_r(&self) -> CalculatorFloat {
     633           5 :         CalculatorFloat::from(1.0)
     634           5 :     }
     635             :     /// Returns the beta_i parameter of the operation.
     636             :     ///
     637             :     /// # Returns
     638             :     ///
     639             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     640           5 :     fn beta_i(&self) -> CalculatorFloat {
     641           5 :         CalculatorFloat::from(0.0)
     642           5 :     }
     643             :     /// Returns global_phase parameter of the operation.
     644             :     ///
     645             :     /// # Returns
     646             :     ///
     647             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     648           5 :     fn global_phase(&self) -> CalculatorFloat {
     649           5 :         CalculatorFloat::from(PI / 2.0)
     650           5 :     }
     651             : }
     652             : 
     653             : /// The Pauli Z gate.
     654             : ///
     655             : /// $$
     656             : /// U = \begin{pmatrix}
     657             : /// 1 & 0 \\\\
     658             : /// 0 & -1
     659             : /// \end{pmatrix}
     660             : /// $$
     661             : ///
     662             : #[derive(
     663           4 :     Debug,
     664          21 :     Clone,
     665          18 :     PartialEq,
     666           3 :     roqoqo_derive::InvolveQubits,
     667          34 :     roqoqo_derive::Operate,
     668           3 :     roqoqo_derive::Substitute,
     669           8 :     roqoqo_derive::OperateSingleQubit,
     670             : )]
     671             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     672             : pub struct PauliZ {
     673             :     /// The qubit the unitary gate is applied to.
     674             :     qubit: usize,
     675             : }
     676             : 
     677             : #[allow(non_upper_case_globals)]
     678             : const TAGS_PauliZ: &[&str; 4] = &[
     679             :     "Operation",
     680             :     "GateOperation",
     681             :     "SingleQubitGateOperation",
     682             :     "PauliZ",
     683             : ];
     684             : 
     685             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     686             : impl OperateGate for PauliZ {
     687             :     /// Returns unitary matrix of the gate.
     688             :     ///
     689             :     /// # Returns
     690             :     ///
     691             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     692             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
     693           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     694           2 :         Ok(array![
     695           2 :             [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)],
     696           2 :             [Complex64::new(0.0, 0.0), Complex64::new(-1.0, 0.0)]
     697           2 :         ])
     698           2 :     }
     699             : }
     700             : 
     701             : /// Trait for unitary operations acting on exactly one qubit.
     702             : impl OperateSingleQubitGate for PauliZ {
     703             :     /// Returns the alpha_r parameter of the operation.
     704             :     ///
     705             :     /// # Returns
     706             :     ///
     707             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     708           5 :     fn alpha_r(&self) -> CalculatorFloat {
     709           5 :         CalculatorFloat::from(0.0)
     710           5 :     }
     711             :     /// Returns the alpha_i parameter of the operation.
     712             :     ///
     713             :     /// # Returns
     714             :     ///
     715             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     716           5 :     fn alpha_i(&self) -> CalculatorFloat {
     717           5 :         CalculatorFloat::from(-1.0)
     718           5 :     }
     719             :     /// Returns the beta_r parameter of the operation.
     720             :     ///
     721             :     /// # Returns
     722             :     ///
     723             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     724           5 :     fn beta_r(&self) -> CalculatorFloat {
     725           5 :         CalculatorFloat::from(0.0)
     726           5 :     }
     727             :     /// Returns the beta_i parameter of the operation.
     728             :     ///
     729             :     /// # Returns
     730             :     ///
     731             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     732           5 :     fn beta_i(&self) -> CalculatorFloat {
     733           5 :         CalculatorFloat::from(0.0)
     734           5 :     }
     735             :     /// Returns global_phase parameter of the operation.
     736             :     ///
     737             :     /// # Returns
     738             :     ///
     739             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     740           5 :     fn global_phase(&self) -> CalculatorFloat {
     741           5 :         CalculatorFloat::from(PI / 2.0)
     742           5 :     }
     743             : }
     744             : 
     745             : /// The square root of the XPower gate: $e^{-i \frac{\pi}{4} \sigma^x}$.
     746             : ///
     747             : /// $$
     748             : /// U = \frac{1}{\sqrt(2)}\begin{pmatrix}
     749             : /// 1 & -i \\\\
     750             : /// -i & 1
     751             : /// \end{pmatrix}
     752             : /// $$
     753             : ///
     754             : #[derive(
     755           1 :     Debug,
     756           8 :     Clone,
     757           8 :     PartialEq,
     758           3 :     roqoqo_derive::InvolveQubits,
     759          25 :     roqoqo_derive::Operate,
     760           3 :     roqoqo_derive::Substitute,
     761           3 :     roqoqo_derive::OperateSingleQubit,
     762             : )]
     763             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     764             : pub struct SqrtPauliX {
     765             :     /// The qubit the unitary gate is applied to.
     766             :     qubit: usize,
     767             : }
     768             : 
     769             : #[allow(non_upper_case_globals)]
     770             : const TAGS_SqrtPauliX: &[&str; 4] = &[
     771             :     "Operation",
     772             :     "GateOperation",
     773             :     "SingleQubitGateOperation",
     774             :     "SqrtPauliX",
     775             : ];
     776             : 
     777             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     778             : impl OperateGate for SqrtPauliX {
     779             :     /// Returns unitary matrix of the gate.
     780             :     ///
     781             :     /// # Returns
     782             :     ///
     783             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     784             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
     785           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     786           2 :         let theta: f64 = PI / 2.0;
     787           2 :         let c: f64 = (theta / 2.0).cos();
     788           2 :         let s: f64 = (theta / 2.0).sin();
     789           2 :         Ok(array![
     790           2 :             [Complex64::new(c, 0.0), Complex64::new(0.0, -1.0 * s)],
     791           2 :             [Complex64::new(0.0, -1.0 * s), Complex64::new(c, 0.0)]
     792           2 :         ])
     793           2 :     }
     794             : }
     795             : 
     796             : /// Trait for unitary operations acting on exactly one qubit.
     797             : impl OperateSingleQubitGate for SqrtPauliX {
     798             :     /// Returns the alpha_r parameter of the operation.
     799             :     ///
     800             :     /// # Returns
     801             :     ///
     802             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     803           2 :     fn alpha_r(&self) -> CalculatorFloat {
     804           2 :         CalculatorFloat::from((PI / 4.0).cos())
     805           2 :     }
     806             :     /// Returns the alpha_i parameter of the operation.
     807             :     ///
     808             :     /// # Returns
     809             :     ///
     810             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     811           2 :     fn alpha_i(&self) -> CalculatorFloat {
     812           2 :         CalculatorFloat::from(0.0)
     813           2 :     }
     814             :     /// Returns the beta_r parameter of the operation.
     815             :     ///
     816             :     /// # Returns
     817             :     ///
     818             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     819           2 :     fn beta_r(&self) -> CalculatorFloat {
     820           2 :         CalculatorFloat::from(0.0)
     821           2 :     }
     822             :     /// Returns the beta_i parameter of the operation.
     823             :     ///
     824             :     /// # Returns
     825             :     ///
     826             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     827           2 :     fn beta_i(&self) -> CalculatorFloat {
     828           2 :         CalculatorFloat::from((PI / 4.0).sin() * (-1.0))
     829           2 :     }
     830             :     /// Returns global_phase parameter of the operation.
     831             :     ///
     832             :     /// # Returns
     833             :     ///
     834             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     835           2 :     fn global_phase(&self) -> CalculatorFloat {
     836           2 :         CalculatorFloat::from(0.0)
     837           2 :     }
     838             : }
     839             : 
     840             : /// The inverse square root of the XPower gate: $e^{i \frac{\pi}{2} \sigma^x}$.
     841             : ///
     842             : /// $$
     843             : /// U = \frac{1}{\sqrt{2}} \begin{pmatrix}
     844             : /// 1 & i \\\\
     845             : ///  i & 1
     846             : /// \end{pmatrix}
     847             : /// $$
     848             : ///
     849             : #[derive(
     850           1 :     Debug,
     851           8 :     Clone,
     852           8 :     PartialEq,
     853           3 :     roqoqo_derive::InvolveQubits,
     854          25 :     roqoqo_derive::Operate,
     855           3 :     roqoqo_derive::Substitute,
     856           3 :     roqoqo_derive::OperateSingleQubit,
     857             : )]
     858             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     859             : pub struct InvSqrtPauliX {
     860             :     /// The qubit the unitary gate is applied to.
     861             :     qubit: usize,
     862             : }
     863             : 
     864             : #[allow(non_upper_case_globals)]
     865             : const TAGS_InvSqrtPauliX: &[&str; 4] = &[
     866             :     "Operation",
     867             :     "GateOperation",
     868             :     "SingleQubitGateOperation",
     869             :     "InvSqrtPauliX",
     870             : ];
     871             : 
     872             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     873             : impl OperateGate for InvSqrtPauliX {
     874             :     /// Returns unitary matrix of the gate.
     875             :     ///
     876             :     /// # Returns
     877             :     ///
     878             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     879             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
     880           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     881           2 :         let theta: f64 = PI / 2.0;
     882           2 :         let c: f64 = (theta / 2.0).cos();
     883           2 :         let s: f64 = (theta / 2.0).sin();
     884           2 :         Ok(array![
     885           2 :             [Complex64::new(c, 0.0), Complex64::new(0.0, 1.0 * s)],
     886           2 :             [Complex64::new(0.0, 1.0 * s), Complex64::new(c, 0.0)]
     887           2 :         ])
     888           2 :     }
     889             : }
     890             : 
     891             : /// Trait for unitary operations acting on exactly one qubit.
     892             : impl OperateSingleQubitGate for InvSqrtPauliX {
     893             :     /// Returns the alpha_r parameter of the operation.
     894             :     ///
     895             :     /// # Returns
     896             :     ///
     897             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     898           2 :     fn alpha_r(&self) -> CalculatorFloat {
     899           2 :         CalculatorFloat::from((PI / 4.0).cos())
     900           2 :     }
     901             :     /// Returns the alpha_i parameter of the operation.
     902             :     ///
     903             :     /// # Returns
     904             :     ///
     905             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     906           2 :     fn alpha_i(&self) -> CalculatorFloat {
     907           2 :         CalculatorFloat::from(0.0)
     908           2 :     }
     909             :     /// Returns the beta_r parameter of the operation.
     910             :     ///
     911             :     /// # Returns
     912             :     ///
     913             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
     914           2 :     fn beta_r(&self) -> CalculatorFloat {
     915           2 :         CalculatorFloat::from(0.0)
     916           2 :     }
     917             :     /// Returns the beta_i parameter of the operation.
     918             :     ///
     919             :     /// # Returns
     920             :     ///
     921             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
     922           2 :     fn beta_i(&self) -> CalculatorFloat {
     923           2 :         CalculatorFloat::from((PI / 4.0).sin())
     924           2 :     }
     925             :     /// Returns global_phase parameter of the operation.
     926             :     ///
     927             :     /// # Returns
     928             :     ///
     929             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
     930           2 :     fn global_phase(&self) -> CalculatorFloat {
     931           2 :         CalculatorFloat::from(0.0)
     932           2 :     }
     933             : }
     934             : 
     935             : /// The Hadamard gate.
     936             : ///
     937             : /// $$
     938             : /// U = \frac{1}{\sqrt{2}} \begin{pmatrix}
     939             : /// 1 & 1\\\\
     940             : ///  1 & -1
     941             : /// \end{pmatrix}
     942             : /// $$
     943             : ///
     944             : #[derive(
     945           1 :     Debug,
     946           8 :     Clone,
     947          18 :     PartialEq,
     948           3 :     roqoqo_derive::InvolveQubits,
     949          46 :     roqoqo_derive::Operate,
     950           3 :     roqoqo_derive::Substitute,
     951           3 :     roqoqo_derive::OperateSingleQubit,
     952             : )]
     953             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
     954             : pub struct Hadamard {
     955             :     /// The qubit the unitary gate is applied to.
     956             :     qubit: usize,
     957             : }
     958             : 
     959             : #[allow(non_upper_case_globals)]
     960             : const TAGS_Hadamard: &[&str; 4] = &[
     961             :     "Operation",
     962             :     "GateOperation",
     963             :     "SingleQubitGateOperation",
     964             :     "Hadamard",
     965             : ];
     966             : 
     967             : /// Trait for all operations acting with a unitary gate on a set of qubits.
     968             : impl OperateGate for Hadamard {
     969             :     /// Returns unitary matrix of the gate.
     970             :     ///
     971             :     /// # Returns
     972             :     ///
     973             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
     974             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
     975           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
     976           2 :         let f: f64 = 1.0 / ((2.0_f64).sqrt());
     977           2 :         Ok(array![
     978           2 :             [Complex64::new(f, 0.0), Complex64::new(f, 0.0)],
     979           2 :             [Complex64::new(f, 0.0), Complex64::new(-1.0 * f, 0.0)]
     980           2 :         ])
     981           2 :     }
     982             : }
     983             : 
     984             : /// Trait for unitary operations acting on exactly one qubit.
     985             : impl OperateSingleQubitGate for Hadamard {
     986             :     /// Returns the alpha_r parameter of the operation.
     987             :     ///
     988             :     /// # Returns
     989             :     ///
     990             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
     991           3 :     fn alpha_r(&self) -> CalculatorFloat {
     992           3 :         CalculatorFloat::from(0.0)
     993           3 :     }
     994             :     /// Returns the alpha_i parameter of the operation.
     995             :     ///
     996             :     /// # Returns
     997             :     ///
     998             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
     999           3 :     fn alpha_i(&self) -> CalculatorFloat {
    1000           3 :         CalculatorFloat::from(-1.0 / ((2.0_f64).sqrt()))
    1001           3 :     }
    1002             :     /// Returns the beta_r parameter of the operation.
    1003             :     ///
    1004             :     /// # Returns
    1005             :     ///
    1006             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
    1007           3 :     fn beta_r(&self) -> CalculatorFloat {
    1008           3 :         CalculatorFloat::from(0.0)
    1009           3 :     }
    1010             :     /// Returns the beta_i parameter of the operation.
    1011             :     ///
    1012             :     /// # Returns
    1013             :     ///
    1014             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
    1015           3 :     fn beta_i(&self) -> CalculatorFloat {
    1016           3 :         CalculatorFloat::from(-1.0 / ((2.0_f64).sqrt()))
    1017           3 :     }
    1018             :     /// Returns global_phase parameter of the operation.
    1019             :     ///
    1020             :     /// # Returns
    1021             :     ///
    1022             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
    1023           2 :     fn global_phase(&self) -> CalculatorFloat {
    1024           2 :         CalculatorFloat::from(PI / 2.0)
    1025           2 :     }
    1026             : }
    1027             : 
    1028             : /// The S gate.
    1029             : ///
    1030             : /// $$
    1031             : /// U = \frac{1}{\sqrt{2}} \begin{pmatrix}
    1032             : /// 1 & 0\\\\
    1033             : ///  0 & i
    1034             : /// \end{pmatrix}
    1035             : /// $$
    1036             : ///
    1037             : #[derive(
    1038           1 :     Debug,
    1039           8 :     Clone,
    1040           8 :     PartialEq,
    1041           3 :     roqoqo_derive::InvolveQubits,
    1042          25 :     roqoqo_derive::Operate,
    1043           3 :     roqoqo_derive::Substitute,
    1044           3 :     roqoqo_derive::OperateSingleQubit,
    1045             : )]
    1046             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
    1047             : pub struct SGate {
    1048             :     /// The qubit the unitary gate is applied to.
    1049             :     qubit: usize,
    1050             : }
    1051             : 
    1052             : #[allow(non_upper_case_globals)]
    1053             : const TAGS_SGate: &[&str; 4] = &[
    1054             :     "Operation",
    1055             :     "GateOperation",
    1056             :     "SingleQubitGateOperation",
    1057             :     "SGate",
    1058             : ];
    1059             : 
    1060             : /// Trait for all operations acting with a unitary gate on a set of qubits.
    1061             : impl OperateGate for SGate {
    1062             :     /// Returns unitary matrix of the gate.
    1063             :     ///
    1064             :     /// # Returns
    1065             :     ///
    1066             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
    1067             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
    1068           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
    1069           2 :         Ok(array![
    1070           2 :             [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)],
    1071           2 :             [Complex64::new(0.0, 0.0), Complex64::new(0.0, 1.0)]
    1072           2 :         ])
    1073           2 :     }
    1074             : }
    1075             : 
    1076             : /// Trait for unitary operations acting on exactly one qubit.
    1077             : impl OperateSingleQubitGate for SGate {
    1078             :     /// Returns the alpha_r parameter of the operation.
    1079             :     ///
    1080             :     /// # Returns
    1081             :     ///
    1082             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
    1083           2 :     fn alpha_r(&self) -> CalculatorFloat {
    1084           2 :         CalculatorFloat::from(1.0 / ((2.0_f64).sqrt()))
    1085           2 :     }
    1086             :     /// Returns the alpha_i parameter of the operation.
    1087             :     ///
    1088             :     /// # Returns
    1089             :     ///
    1090             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
    1091           2 :     fn alpha_i(&self) -> CalculatorFloat {
    1092           2 :         CalculatorFloat::from(-1.0 / ((2.0_f64).sqrt()))
    1093           2 :     }
    1094             :     /// Returns the beta_r parameter of the operation.
    1095             :     ///
    1096             :     /// # Returns
    1097             :     ///
    1098             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
    1099           2 :     fn beta_r(&self) -> CalculatorFloat {
    1100           2 :         CalculatorFloat::from(0.0)
    1101           2 :     }
    1102             :     /// Returns the beta_i parameter of the operation.
    1103             :     ///
    1104             :     /// # Returns
    1105             :     ///
    1106             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
    1107           2 :     fn beta_i(&self) -> CalculatorFloat {
    1108           2 :         CalculatorFloat::from(0.0)
    1109           2 :     }
    1110             :     /// Returns global_phase parameter of the operation.
    1111             :     ///
    1112             :     /// # Returns
    1113             :     ///
    1114             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
    1115           2 :     fn global_phase(&self) -> CalculatorFloat {
    1116           2 :         CalculatorFloat::from(PI / 4.0)
    1117           2 :     }
    1118             : }
    1119             : 
    1120             : /// The T gate.
    1121             : ///
    1122             : /// $$
    1123             : /// U = \frac{1}{\sqrt{2}} \begin{pmatrix}
    1124             : /// 1 & 0\\\\
    1125             : ///  0 & e^{i \frac{\pi}{4}}
    1126             : /// \end{pmatrix}
    1127             : /// $$
    1128             : ///
    1129             : #[derive(
    1130           1 :     Debug,
    1131           8 :     Clone,
    1132           8 :     PartialEq,
    1133           3 :     roqoqo_derive::InvolveQubits,
    1134          25 :     roqoqo_derive::Operate,
    1135           3 :     roqoqo_derive::Substitute,
    1136           3 :     roqoqo_derive::OperateSingleQubit,
    1137             : )]
    1138             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
    1139             : pub struct TGate {
    1140             :     /// The qubit the unitary gate is applied to.
    1141             :     qubit: usize,
    1142             : }
    1143             : 
    1144             : #[allow(non_upper_case_globals)]
    1145             : const TAGS_TGate: &[&str; 4] = &[
    1146             :     "Operation",
    1147             :     "GateOperation",
    1148             :     "SingleQubitGateOperation",
    1149             :     "TGate",
    1150             : ];
    1151             : 
    1152             : /// Trait for all operations acting with a unitary gate on a set of qubits.
    1153             : impl OperateGate for TGate {
    1154             :     /// Returns unitary matrix of the gate.
    1155             :     ///
    1156             :     /// # Returns
    1157             :     ///
    1158             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
    1159             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
    1160           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
    1161           2 :         Ok(array![
    1162           2 :             [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)],
    1163           2 :             [
    1164           2 :                 Complex64::new(0.0, 0.0),
    1165           2 :                 Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin())
    1166           2 :             ] //exp(i*pi/4) = cos(pi/4) + i*sin(pi/4)
    1167           2 :         ])
    1168           2 :     }
    1169             : }
    1170             : 
    1171             : /// Trait for unitary operations acting on exactly one qubit.
    1172             : impl OperateSingleQubitGate for TGate {
    1173             :     /// Returns the alpha_r parameter of the operation.
    1174             :     ///
    1175             :     /// # Returns
    1176             :     ///
    1177             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
    1178           2 :     fn alpha_r(&self) -> CalculatorFloat {
    1179           2 :         CalculatorFloat::from((PI / 8.0).cos())
    1180           2 :     }
    1181             :     /// Returns the alpha_i parameter of the operation.
    1182             :     ///
    1183             :     /// # Returns
    1184             :     ///
    1185             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
    1186           2 :     fn alpha_i(&self) -> CalculatorFloat {
    1187           2 :         CalculatorFloat::from((-1.0) * (PI / 8.0).sin())
    1188           2 :     }
    1189             :     /// Returns the beta_r parameter of the operation.
    1190             :     ///
    1191             :     /// # Returns
    1192             :     ///
    1193             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
    1194           2 :     fn beta_r(&self) -> CalculatorFloat {
    1195           2 :         CalculatorFloat::from(0.0)
    1196           2 :     }
    1197             :     /// Returns the beta_i parameter of the operation.
    1198             :     ///
    1199             :     /// # Returns
    1200             :     ///
    1201             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
    1202           2 :     fn beta_i(&self) -> CalculatorFloat {
    1203           2 :         CalculatorFloat::from(0.0)
    1204           2 :     }
    1205             :     /// Returns global_phase parameter of the operation.
    1206             :     ///
    1207             :     /// # Returns
    1208             :     ///
    1209             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
    1210           2 :     fn global_phase(&self) -> CalculatorFloat {
    1211           2 :         CalculatorFloat::from(PI / 8.0)
    1212           2 :     }
    1213             : }
    1214             : 
    1215             : /// The phase shift gate applied on state |1>.
    1216             : ///
    1217             : /// Rotation around Z-axis by an arbitrary angle $\theta$ (AC Stark shift of the state |1>).
    1218             : ///
    1219             : /// $$
    1220             : /// U = \begin{pmatrix}
    1221             : /// 1 & 0\\\\
    1222             : ///  0 & e^{i \theta}
    1223             : /// \end{pmatrix}
    1224             : /// $$
    1225             : ///
    1226             : #[derive(
    1227           1 :     Debug,
    1228           9 :     Clone,
    1229          10 :     PartialEq,
    1230           3 :     roqoqo_derive::InvolveQubits,
    1231          35 :     roqoqo_derive::Operate,
    1232           5 :     roqoqo_derive::Substitute,
    1233           3 :     roqoqo_derive::OperateSingleQubit,
    1234          19 :     roqoqo_derive::Rotate,
    1235             : )]
    1236             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
    1237             : pub struct PhaseShiftState1 {
    1238             :     /// The qubit the unitary gate is applied to.
    1239             :     qubit: usize,
    1240             :     /// The angle $\theta$ of the rotation, in the interval from 0 to $2 \pi$.
    1241             :     theta: CalculatorFloat,
    1242             : }
    1243             : 
    1244             : #[allow(non_upper_case_globals)]
    1245             : const TAGS_PhaseShiftState1: &[&str; 5] = &[
    1246             :     "Operation",
    1247             :     "GateOperation",
    1248             :     "SingleQubitGateOperation",
    1249             :     "Rotation",
    1250             :     "PhaseShiftState1",
    1251             : ];
    1252             : 
    1253             : /// Trait for all operations acting with a unitary gate on a set of qubits.
    1254             : impl OperateGate for PhaseShiftState1 {
    1255             :     /// Returns unitary matrix of the gate.
    1256             :     ///
    1257             :     /// # Returns
    1258             :     ///
    1259             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
    1260             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
    1261           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
    1262           2 :         let theta: f64 = f64::try_from(self.theta().clone())?;
    1263           2 :         Ok(array![
    1264           2 :             [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)],
    1265           2 :             [
    1266           2 :                 Complex64::new(0.0, 0.0),
    1267           2 :                 Complex64::new(theta.cos(), theta.sin())
    1268           2 :             ]
    1269           2 :         ])
    1270           2 :     }
    1271             : }
    1272             : 
    1273             : /// Trait for unitary operations acting on exactly one qubit.
    1274             : impl OperateSingleQubitGate for PhaseShiftState1 {
    1275             :     /// Returns the alpha_r parameter of the operation.
    1276             :     ///
    1277             :     /// # Returns
    1278             :     ///
    1279             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
    1280           3 :     fn alpha_r(&self) -> CalculatorFloat {
    1281           3 :         (self.theta().clone() / 2.0).cos()
    1282           3 :     }
    1283             :     /// Returns the alpha_i parameter of the operation.
    1284             :     ///
    1285             :     /// # Returns
    1286             :     ///
    1287             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
    1288           3 :     fn alpha_i(&self) -> CalculatorFloat {
    1289           3 :         (self.theta().clone() / 2.0).sin() * (-1.0)
    1290           3 :     }
    1291             :     /// Returns the beta_r parameter of the operation.
    1292             :     ///
    1293             :     /// # Returns
    1294             :     ///
    1295             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
    1296           3 :     fn beta_r(&self) -> CalculatorFloat {
    1297           3 :         CalculatorFloat::from(0.0)
    1298           3 :     }
    1299             :     /// Returns the beta_i parameter of the operation.
    1300             :     ///
    1301             :     /// # Returns
    1302             :     ///
    1303             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
    1304           3 :     fn beta_i(&self) -> CalculatorFloat {
    1305           3 :         CalculatorFloat::from(0.0)
    1306           3 :     }
    1307             :     /// Returns global_phase parameter of the operation.
    1308             :     ///
    1309             :     /// # Returns
    1310             :     ///
    1311             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
    1312           3 :     fn global_phase(&self) -> CalculatorFloat {
    1313           3 :         self.theta().clone() / 2.0
    1314           3 :     }
    1315             : }
    1316             : 
    1317             : /// The phase shift gate applied on state |0>.
    1318             : ///
    1319             : /// Rotation around Z-axis by an arbitrary angle $\theta$ (AC Stark shift of the state |0>).
    1320             : ///
    1321             : /// $$
    1322             : /// U = \begin{pmatrix}
    1323             : /// e^{i \theta} & 0\\\\
    1324             : ///  0 & 1
    1325             : /// \end{pmatrix}
    1326             : /// $$
    1327             : ///
    1328             : #[derive(
    1329           1 :     Debug,
    1330           9 :     Clone,
    1331          10 :     PartialEq,
    1332           3 :     roqoqo_derive::InvolveQubits,
    1333          35 :     roqoqo_derive::Operate,
    1334           5 :     roqoqo_derive::Substitute,
    1335           3 :     roqoqo_derive::OperateSingleQubit,
    1336          19 :     roqoqo_derive::Rotate,
    1337             : )]
    1338             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
    1339             : pub struct PhaseShiftState0 {
    1340             :     /// The qubit the unitary gate is applied to.
    1341             :     qubit: usize,
    1342             :     /// The angle $\theta$ of the rotation, in the interval from 0 to $2 \pi$.
    1343             :     theta: CalculatorFloat,
    1344             : }
    1345             : 
    1346             : #[allow(non_upper_case_globals)]
    1347             : const TAGS_PhaseShiftState0: &[&str; 5] = &[
    1348             :     "Operation",
    1349             :     "GateOperation",
    1350             :     "SingleQubitGateOperation",
    1351             :     "Rotation",
    1352             :     "PhaseShiftState0",
    1353             : ];
    1354             : 
    1355             : /// Trait for all operations acting with a unitary gate on a set of qubits.
    1356             : impl OperateGate for PhaseShiftState0 {
    1357             :     /// Returns unitary matrix of the gate.
    1358             :     ///
    1359             :     /// # Returns
    1360             :     ///
    1361             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
    1362             :     /// * `Err(RoqoqoError)` - The parameter conversion to f64 failed (here, not possible).
    1363           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
    1364           2 :         let theta: f64 = f64::try_from(self.theta().clone())?;
    1365           2 :         Ok(array![
    1366           2 :             [
    1367           2 :                 Complex64::new(theta.cos(), theta.sin()),
    1368           2 :                 Complex64::new(0.0, 0.0)
    1369           2 :             ],
    1370           2 :             [Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0)]
    1371           2 :         ])
    1372           2 :     }
    1373             : }
    1374             : 
    1375             : /// Trait for unitary operations acting on exactly one qubit.
    1376             : impl OperateSingleQubitGate for PhaseShiftState0 {
    1377             :     /// Returns the alpha_r parameter of the operation.
    1378             :     ///
    1379             :     /// # Returns
    1380             :     ///
    1381             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
    1382           3 :     fn alpha_r(&self) -> CalculatorFloat {
    1383           3 :         (self.theta().clone() / 2.0).cos()
    1384           3 :     }
    1385             :     /// Returns the alpha_i parameter of the operation.
    1386             :     ///
    1387             :     /// # Returns
    1388             :     ///
    1389             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
    1390           3 :     fn alpha_i(&self) -> CalculatorFloat {
    1391           3 :         (self.theta().clone() / 2.0).sin()
    1392           3 :     }
    1393             :     /// Returns the beta_r parameter of the operation.
    1394             :     ///
    1395             :     /// # Returns
    1396             :     ///
    1397             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
    1398           3 :     fn beta_r(&self) -> CalculatorFloat {
    1399           3 :         CalculatorFloat::from(0.0)
    1400           3 :     }
    1401             :     /// Returns the beta_i parameter of the operation.
    1402             :     ///
    1403             :     /// # Returns
    1404             :     ///
    1405             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
    1406           3 :     fn beta_i(&self) -> CalculatorFloat {
    1407           3 :         CalculatorFloat::from(0.0)
    1408           3 :     }
    1409             :     /// Returns global_phase parameter of the operation.
    1410             :     ///
    1411             :     /// # Returns
    1412             :     ///
    1413             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
    1414           3 :     fn global_phase(&self) -> CalculatorFloat {
    1415           3 :         self.theta().clone() / 2.0
    1416           3 :     }
    1417             : }
    1418             : 
    1419             : /// Implements a rotation around an axis in the x-y plane in spherical coordinates.
    1420             : ///
    1421             : /// $$
    1422             : /// U = \begin{pmatrix}
    1423             : /// \cos(\frac{\theta}{2}) & 0\\\\
    1424             : /// 0 & \cos(\frac{\theta}{2})
    1425             : /// \end{pmatrix}
    1426             : /// \+ \begin{pmatrix}
    1427             : /// -i \sin(\frac{\theta}{2}) v_z  &  \sin(\frac{\theta}{2}) \left(-i v_x - v_y \right)\\\\
    1428             : /// \sin(\frac{\theta}{2}) \left(-i v_x + v_y \right) & i \sin(\frac{\theta}{2}) v_z
    1429             : /// \end{pmatrix}
    1430             : ///  $$
    1431             : ///
    1432             : /// with
    1433             : /// $ v_x = \sin(\theta_{sph}) \cos(\phi_{sph}) $,
    1434             : /// $ v_y = \sin(\theta_{sph}) \sin(\phi_{sph}) $,
    1435             : /// $ v_z = \cos(\theta_{sph})$.
    1436             : ///
    1437             : #[derive(
    1438           1 :     Debug,
    1439          11 :     Clone,
    1440          10 :     PartialEq,
    1441           3 :     roqoqo_derive::InvolveQubits,
    1442           3 :     roqoqo_derive::Operate,
    1443           5 :     roqoqo_derive::Substitute,
    1444           5 :     roqoqo_derive::OperateSingleQubit,
    1445          12 :     roqoqo_derive::Rotate,
    1446             : )]
    1447             : #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
    1448             : pub struct RotateAroundSphericalAxis {
    1449             :     /// The qubit the unitary gate is applied to.
    1450             :     qubit: usize,
    1451             :     /// The angle $\theta$ of the rotation, in the interval from 0 to $2^* 2 \pi$.
    1452             :     theta: CalculatorFloat,
    1453             :     /// The rotation axis, unit-vector spherical coordinates $\theta_{sph}$.
    1454             :     spherical_theta: CalculatorFloat,
    1455             :     /// The rotation axis, unit-vector spherical coordinates $\phi_{sph}$  gives the angle in the x-y plane.
    1456             :     spherical_phi: CalculatorFloat,
    1457             : }
    1458             : 
    1459             : #[allow(non_upper_case_globals)]
    1460             : const TAGS_RotateAroundSphericalAxis: &[&str; 5] = &[
    1461             :     "Operation",
    1462             :     "GateOperation",
    1463             :     "SingleQubitGateOperation",
    1464             :     "Rotation",
    1465             :     "RotateAroundSphericalAxis",
    1466             : ];
    1467             : 
    1468             : /// Trait for all operations acting with a unitary gate on a set of qubits.
    1469             : impl OperateGate for RotateAroundSphericalAxis {
    1470             :     /// Returns unitary matrix of the gate.
    1471             :     ///
    1472             :     /// # Returns
    1473             :     ///
    1474             :     /// * `Ok(Array2<Complex64>)` - The unitary matrix representation of the gate.
    1475             :     /// * `Err(RoqoqoError)` - The conversion of parameters to f64 failed.
    1476           2 :     fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
    1477           2 :         let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
    1478           2 :         let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
    1479           2 :         let vx: f64 = ((f64::try_from(self.spherical_theta.clone())?).sin())
    1480           2 :             * ((f64::try_from(self.spherical_phi.clone())?).cos());
    1481           2 :         let vy: f64 = ((f64::try_from(self.spherical_theta.clone())?).sin())
    1482           2 :             * ((f64::try_from(self.spherical_phi.clone())?).sin());
    1483           2 :         let vz: f64 = (f64::try_from(self.spherical_theta.clone())?).cos();
    1484           2 :         Ok(array![
    1485           2 :             [
    1486           2 :                 Complex64::new(c, -1.0 * s * vz),
    1487           2 :                 Complex64::new(-1.0 * s * vy, -1.0 * s * vx)
    1488           2 :             ],
    1489           2 :             [
    1490           2 :                 Complex64::new(s * vy, -1.0 * s * vx),
    1491           2 :                 Complex64::new(c, s * vz)
    1492           2 :             ]
    1493           2 :         ])
    1494           2 :     }
    1495             : }
    1496             : 
    1497             : /// Trait for unitary operations acting on exactly one qubit.
    1498             : impl OperateSingleQubitGate for RotateAroundSphericalAxis {
    1499             :     /// Returns the alpha_r parameter of the operation.
    1500             :     ///
    1501             :     /// # Returns
    1502             :     ///
    1503             :     /// * `alpha_r` - The real part $\alpha_r$ of the on-diagonal elements of the single-qubit unitary matrix.
    1504          11 :     fn alpha_r(&self) -> CalculatorFloat {
    1505          11 :         (self.theta.clone() / 2.0).cos()
    1506          11 :     }
    1507             :     /// Returns the alpha_i parameter of the operation.
    1508             :     ///
    1509             :     /// # Returns
    1510             :     ///
    1511             :     /// * `alpha_i` - The imaginary part $ \alpha_i $ of the on-diagonal elements of the single-qubit unitary matrix.
    1512          11 :     fn alpha_i(&self) -> CalculatorFloat {
    1513          11 :         let s = (self.theta.clone() / 2.0).sin();
    1514          11 :         let vz = (self.spherical_theta.clone()).cos();
    1515          11 :         s * vz * (-1.0) // CHECK sign (?)
    1516          11 :     }
    1517             :     /// Returns the beta_r parameter of the operation.
    1518             :     ///
    1519             :     /// # Returns
    1520             :     ///
    1521             :     /// * `beta_r` - The real part $ \beta_r $ of the off-diagonal elements of the single-qubit unitary matrix.
    1522          11 :     fn beta_r(&self) -> CalculatorFloat {
    1523          11 :         let s = (self.theta.clone() / 2.0).sin();
    1524          11 :         let vy = (self.spherical_phi.clone()).sin();
    1525          11 :         let st = (self.spherical_theta.clone()).sin();
    1526          11 :         s * vy * st
    1527          11 :     }
    1528             :     /// Returns the beta_i parameter of the operation.
    1529             :     ///
    1530             :     /// # Returns
    1531             :     ///
    1532             :     /// * `beta_i` - The imaginary part $ \beta_i $ of the off-diagonal elements of the single-qubit unitary matrix.
    1533          11 :     fn beta_i(&self) -> CalculatorFloat {
    1534          11 :         let s = (self.theta.clone() / 2.0).sin();
    1535          11 :         let vx = (self.spherical_phi.clone()).cos();
    1536          11 :         let st = (self.spherical_theta.clone()).sin();
    1537          11 :         s * vx * st * (-1.0)
    1538          11 :     }
    1539             :     /// Returns global_phase parameter of the operation.
    1540             :     ///
    1541             :     /// # Returns
    1542             :     ///
    1543             :     /// * `global_phase` - The global phase phi $ \phi $ of the single-qubit unitary.
    1544          11 :     fn global_phase(&self) -> CalculatorFloat {
    1545          11 :         CalculatorFloat::from(0.0)
    1546          11 :     }
    1547             : }

Generated by: LCOV version 1.13