1use crate::{components::state::State, errors::Error};
2use dyn_clone::DynClone;
3use num_complex::Complex;
4use rayon::prelude::*;
5use std::{collections::HashSet, fmt::Debug};
6#[cfg(feature = "gpu")]
7use crate::components::gpu_context::{GPU_CONTEXT, KernelType};
8#[cfg(feature = "gpu")]
9use ocl::prm::Float2;
10#[cfg(feature = "gpu")]
11use std::f64::consts::PI;
12#[cfg(feature = "gpu")]
13use crate::components::gpu_context::GpuKernelArgs;
14use crate::compiler::compilable::Compilable;
15
16const PARALLEL_THRESHOLD_NUM_QUBITS: usize = 10;
18
19 const OPENCL_THRESHOLD_NUM_QUBITS: usize = 15;
21
22#[cfg(feature = "gpu")]
23fn execute_on_gpu(
24 state: &State,
25 target_qubit: usize,
26 control_qubits: &[usize],
27 kernel_type: KernelType,
28 global_work_size: usize,
29 kernel_args: GpuKernelArgs,
30) -> Result<Vec<Complex<f64>>, Error> {
31 let mut context_guard = GPU_CONTEXT.lock().map_err(|_| Error::GpuContextLockError)?;
32 let context = match *context_guard {
33 Ok(ref mut ctx) => ctx,
34 Err(ref e) => return Err(e.clone()), };
36
37 let num_qubits = state.num_qubits();
38 let num_state_elements = state.state_vector.len();
39
40 let state_buffer_cloned = context.ensure_state_buffer(num_state_elements)?.clone();
42
43 let control_qubits_i32: Vec<i32> = control_qubits.iter().map(|&q| q as i32).collect();
44 let control_buffer_len = control_qubits_i32.len();
45 let control_buffer_cloned = context.ensure_control_buffer(control_buffer_len)?.clone();
46
47 let state_vector_f32: Vec<Float2> = state.state_vector.iter()
48 .map(|c| Float2::new(c.re as f32, c.im as f32))
49 .collect();
50
51 state_buffer_cloned.write(&state_vector_f32).enq()
53 .map_err(|e| Error::OpenCLError(format!("Failed to write to state buffer: {}", e)))?;
54
55 if !control_qubits_i32.is_empty() {
56 control_buffer_cloned.write(&control_qubits_i32).enq()
57 .map_err(|e| Error::OpenCLError(format!("Failed to write to control buffer: {}", e)))?;
58 } else {
59 let dummy_control_data = vec![0; 1]; control_buffer_cloned.write(&dummy_control_data).enq()
62 .map_err(|e| Error::OpenCLError(format!("Failed to write to dummy control buffer: {}", e)))?;
63 }
64
65 let mut kernel_builder = context.pro_que.kernel_builder(kernel_type.name());
66 kernel_builder.global_work_size(global_work_size)
67 .arg(&state_buffer_cloned) .arg(num_qubits as i32)
69 .arg(target_qubit as i32)
70 .arg(control_buffer_cloned)
71 .arg(control_qubits_i32.len() as i32);
72
73 match kernel_args {
74 GpuKernelArgs::None => {
75 }
77 GpuKernelArgs::SOrSdag { sign } => {
78 kernel_builder.arg(sign);
79 }
80 GpuKernelArgs::PhaseShift { cos_angle, sin_angle } => {
81 kernel_builder.arg(cos_angle).arg(sin_angle);
82 }
83 GpuKernelArgs::SwapTarget { q1 } => {
84 kernel_builder.arg(q1);
85 }
86 GpuKernelArgs::RotationGate { cos_half_angle, sin_half_angle } => {
87 kernel_builder.arg(cos_half_angle).arg(sin_half_angle);
88 }
89 }
90
91 let kernel = kernel_builder.build()
92 .map_err(|e| Error::OpenCLError(format!("Failed to build kernel '{}': {}", kernel_type.name(), e)))?;
93
94 unsafe {
95 kernel.enq().map_err(|e| Error::OpenCLError(format!("Failed to enqueue kernel: {}", e)))?;
96 }
97
98 let mut state_vector_ocl_result = vec![Float2::new(0.0, 0.0); num_state_elements];
99 state_buffer_cloned.read(&mut state_vector_ocl_result).enq()
101 .map_err(|e| Error::OpenCLError(format!("Failed to read state buffer: {}", e)))?;
102
103 Ok(state_vector_ocl_result.iter()
104 .map(|f2| Complex::new(f2[0] as f64, f2[1] as f64))
105 .collect())
106}
107
108pub trait Operator: Send + Sync + Debug + DynClone {
110 fn apply(
124 &self,
125 state: &State,
126 target_qubits: &[usize],
127 control_qubits: &[usize],
128 ) -> Result<State, Error>;
129
130 fn base_qubits(&self) -> usize;
136
137 fn to_compilable(&self) -> Option<&dyn Compilable> {
145 None
147 }
148}
149
150dyn_clone::clone_trait_object!(Operator);
151
152fn check_controls(index: usize, control_qubits: &[usize]) -> bool {
154 control_qubits
155 .iter()
156 .all(|&qubit| (index >> qubit) & 1 == 1)
157}
158
159fn validate_qubits(
173 state: &State,
174 target_qubits: &[usize],
175 control_qubits: &[usize],
176 expected_targets: usize,
177) -> Result<(), Error> {
178 if target_qubits.len() != expected_targets {
180 return Err(Error::InvalidNumberOfQubits(target_qubits.len()));
181 }
182
183 let num_qubits = state.num_qubits();
184
185 for &target_qubit in target_qubits {
187 if target_qubit >= num_qubits {
188 return Err(Error::InvalidQubitIndex(target_qubit, num_qubits));
189 }
190 }
191
192 for &control_qubit in control_qubits {
194 if control_qubit >= num_qubits {
195 return Err(Error::InvalidQubitIndex(control_qubit, num_qubits));
196 }
197
198 for &target_qubit in target_qubits {
199 if control_qubit == target_qubit {
200 return Err(Error::OverlappingControlAndTargetQubits(
201 control_qubit,
202 target_qubit,
203 ));
204 }
205 }
206 }
207
208 if expected_targets > 1 {
210 if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
211 let mut seen_targets: HashSet<usize> = HashSet::with_capacity(target_qubits.len());
213 for &target_qubit in target_qubits {
214 if !seen_targets.insert(target_qubit) {
215 return Err(Error::InvalidQubitIndex(target_qubit, num_qubits));
216 }
217 }
218 } else {
219 for i in 0..target_qubits.len() {
221 for j in i + 1..target_qubits.len() {
222 if target_qubits[i] == target_qubits[j] {
223 return Err(Error::InvalidQubitIndex(target_qubits[i], num_qubits));
224 }
225 }
226 }
227 }
228 }
229
230 Ok(())
231}
232
233#[derive(Debug, Clone, Copy)]
237pub struct Hadamard;
238
239impl Operator for Hadamard {
240 fn apply(
262 &self,
263 state: &State,
264 target_qubits: &[usize],
265 control_qubits: &[usize],
266 ) -> Result<State, Error> {
267 validate_qubits(state, target_qubits, control_qubits, 1)?;
269
270 let target_qubit: usize = target_qubits[0];
271 let num_qubits: usize = state.num_qubits();
272
273 let sqrt_2_inv: f64 = 1.0 / (2.0f64).sqrt();
275 let dim: usize = 1 << num_qubits;
276 #[allow(unused_assignments)]
277 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
278 let gpu_enabled: bool = cfg!(feature = "gpu");
279
280 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
281 #[cfg(feature = "gpu")]
282 {
283 let global_work_size = if num_qubits > 0 { 1 << (num_qubits - 1) } else { 1 };
284 new_state_vec = execute_on_gpu(
285 state,
286 target_qubit,
287 control_qubits,
288 KernelType::Hadamard,
289 global_work_size,
290 GpuKernelArgs::None,
291 )?;
292 }
293 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
294 new_state_vec = state.state_vector.clone(); if control_qubits.is_empty() {
297 let updates: Vec<(usize, Complex<f64>)> = (0..(1 << (num_qubits - 1)))
299 .into_par_iter()
300 .flat_map(|k| {
301 let i0 = (k >> target_qubit << (target_qubit + 1))
302 | (k & ((1 << target_qubit) - 1));
303 let i1 = i0 | (1 << target_qubit);
304 let amp0 = state.state_vector[i0];
305 let amp1 = state.state_vector[i1];
306 vec![
307 (i0, sqrt_2_inv * (amp0 + amp1)),
308 (i1, sqrt_2_inv * (amp0 - amp1)),
309 ]
310 })
311 .collect();
312 for (idx, val) in updates {
313 new_state_vec[idx] = val;
314 }
315 } else {
316 let updates: Vec<(usize, Complex<f64>)> = (0..dim)
318 .into_par_iter()
319 .filter_map(|i| {
320 if (i >> target_qubit) & 1 == 0 { let j = i | (1 << target_qubit); if check_controls(i, control_qubits) { let amp_i = state.state_vector[i];
324 let amp_j = state.state_vector[j];
325 Some(vec![
326 (i, sqrt_2_inv * (amp_i + amp_j)),
327 (j, sqrt_2_inv * (amp_i - amp_j)),
328 ])
329 } else {
330 None }
332 } else {
333 None }
335 })
336 .flatten()
337 .collect();
338 for (idx, val) in updates {
339 new_state_vec[idx] = val;
340 }
341 }
342 } else {
343 new_state_vec = state.state_vector.clone(); if control_qubits.is_empty() {
346 for k in 0..(1 << (num_qubits - 1)) {
348 let i0 =
349 (k >> target_qubit << (target_qubit + 1)) | (k & ((1 << target_qubit) - 1));
350 let i1 = i0 | (1 << target_qubit);
351 let amp0 = state.state_vector[i0];
352 let amp1 = state.state_vector[i1];
353 new_state_vec[i0] = sqrt_2_inv * (amp0 + amp1);
354 new_state_vec[i1] = sqrt_2_inv * (amp0 - amp1);
355 }
356 } else {
357 for i in 0..dim {
359 if (i >> target_qubit) & 1 == 0 {
360 let j = i | (1 << target_qubit);
361 if check_controls(i, control_qubits) {
362 let amp_i = state.state_vector[i];
363 let amp_j = state.state_vector[j];
364 new_state_vec[i] = sqrt_2_inv * (amp_i + amp_j);
365 new_state_vec[j] = sqrt_2_inv * (amp_i - amp_j);
366 }
367 }
368 }
369 }
370 }
371
372 Ok(State {
373 state_vector: new_state_vec,
374 num_qubits,
375 })
376 }
377
378 fn base_qubits(&self) -> usize {
379 1 }
381
382 fn to_compilable(&self) -> Option<&dyn Compilable> {
383 Some(self)
384 }
385}
386
387#[derive(Debug, Clone, Copy, PartialEq)]
389pub enum Pauli {
390 X,
392 Y,
394 Z,
396}
397
398impl Operator for Pauli {
399 fn apply(
421 &self,
422 state: &State,
423 target_qubits: &[usize],
424 control_qubits: &[usize],
425 ) -> Result<State, Error> {
426 validate_qubits(state, target_qubits, control_qubits, 1)?;
428
429 let target_qubit: usize = target_qubits[0];
430 let num_qubits: usize = state.num_qubits();
431
432 let dim: usize = 1 << num_qubits;
434 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
435 let i_complex: Complex<f64> = Complex::new(0.0, 1.0);
436 let gpu_enabled: bool = cfg!(feature = "gpu");
437
438 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
439 #[cfg(feature = "gpu")]
440 {
441 let kernel_type = match self {
442 Pauli::X => KernelType::PauliX,
443 Pauli::Y => KernelType::PauliY,
444 Pauli::Z => KernelType::PauliZ,
445 };
446 let global_work_size = if num_qubits == 0 {
447 1
448 } else {
449 match self {
450 Pauli::Z => 1 << num_qubits, _ => 1 << (num_qubits - 1), }
453 };
454 new_state_vec = execute_on_gpu(
455 state,
456 target_qubit,
457 control_qubits,
458 kernel_type,
459 global_work_size,
460 GpuKernelArgs::None,
461 )?;
462 }
463 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
464 match self {
466 Pauli::X => {
467 let updates: Vec<(usize, Complex<f64>)> = (0..dim)
468 .into_par_iter()
469 .filter_map(|i| {
470 if check_controls(i, control_qubits) && ((i >> target_qubit) & 1 == 0) {
471 let j = i | (1 << target_qubit);
472 let amp_i = state.state_vector[i];
473 let amp_j = state.state_vector[j];
474 Some(vec![(i, amp_j), (j, amp_i)])
475 } else {
476 None
477 }
478 })
479 .flatten()
480 .collect();
481 for (idx, val) in updates {
482 new_state_vec[idx] = val;
483 }
484 }
485 Pauli::Y => {
486 let updates: Vec<(usize, Complex<f64>)> = (0..dim)
487 .into_par_iter()
488 .filter_map(|i| {
489 if check_controls(i, control_qubits) && ((i >> target_qubit) & 1 == 0) {
490 let j = i | (1 << target_qubit);
491 let amp_i = state.state_vector[i];
492 let amp_j = state.state_vector[j];
493 Some(vec![(i, -i_complex * amp_j), (j, i_complex * amp_i)])
494 } else {
495 None
496 }
497 })
498 .flatten()
499 .collect();
500 for (idx, val) in updates {
501 new_state_vec[idx] = val;
502 }
503 }
504 Pauli::Z => {
505 new_state_vec
506 .par_iter_mut()
507 .enumerate()
508 .for_each(|(i, current_amp_ref)| {
509 if check_controls(i, control_qubits) && ((i >> target_qubit) & 1 == 1) {
510 *current_amp_ref = -state.state_vector[i];
511 }
512 });
513 }
514 }
515 } else {
516 for i in 0..dim {
518 if check_controls(i, control_qubits) {
519 match self {
520 Pauli::X => {
521 if (i >> target_qubit) & 1 == 0 {
522 let j = i | (1 << target_qubit);
523 let amp_i = state.state_vector[i];
524 let amp_j = state.state_vector[j];
525 new_state_vec[i] = amp_j;
526 new_state_vec[j] = amp_i;
527 }
528 }
529 Pauli::Y => {
530 if (i >> target_qubit) & 1 == 0 {
531 let j = i | (1 << target_qubit);
532 let amp_i = state.state_vector[i];
533 let amp_j = state.state_vector[j];
534 new_state_vec[i] = -i_complex * amp_j;
535 new_state_vec[j] = i_complex * amp_i;
536 }
537 }
538 Pauli::Z => {
539 if (i >> target_qubit) & 1 == 1 {
540 new_state_vec[i] = -state.state_vector[i];
541 }
542 }
543 }
544 }
545 }
546 }
547
548 Ok(State {
549 state_vector: new_state_vec,
550 num_qubits: state.num_qubits(),
551 })
552 }
553
554 fn base_qubits(&self) -> usize {
555 1 }
557
558 fn to_compilable(&self) -> Option<&dyn Compilable> {
559 Some(self) }
561}
562
563impl std::fmt::Display for Pauli {
564 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
565 match self {
566 Pauli::X => write!(f, "X"),
567 Pauli::Y => write!(f, "Y"),
568 Pauli::Z => write!(f, "Z"),
569 }
570 }
571}
572
573#[derive(Debug, Clone, Copy)]
577pub struct CNOT;
578
579impl Operator for CNOT {
580 fn apply(
602 &self,
603 state: &State,
604 target_qubits: &[usize],
605 control_qubits: &[usize],
606 ) -> Result<State, Error> {
607 validate_qubits(state, target_qubits, control_qubits, 1)?;
609
610 if control_qubits.len() != 1 {
612 return Err(Error::InvalidNumberOfQubits(control_qubits.len()));
613 }
614
615 let control_qubit: usize = control_qubits[0];
616
617 Pauli::X.apply(state, target_qubits, &[control_qubit])
619 }
620
621 fn base_qubits(&self) -> usize {
622 2 }
624
625 fn to_compilable(&self) -> Option<&dyn Compilable> {
626 Some(self)
627 }
628}
629
630#[derive(Debug, Clone, Copy)]
634pub struct SWAP;
635
636impl Operator for SWAP {
637 fn apply(
660 &self,
661 state: &State,
662 target_qubits: &[usize],
663 control_qubits: &[usize],
664 ) -> Result<State, Error> {
665 validate_qubits(state, target_qubits, control_qubits, 2)?;
667
668 let target_qubit_1: usize = target_qubits[0];
669 let target_qubit_2: usize = target_qubits[1];
670 let num_qubits: usize = state.num_qubits();
671
672 let dim: usize = 1 << num_qubits;
674 #[allow(unused_assignments)] let mut new_state_vec = state.state_vector.clone(); let gpu_enabled: bool = cfg!(feature = "gpu");
677
678 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
679 #[cfg(feature = "gpu")]
680 {
681 let global_work_size = if num_qubits >= 2 { 1 << (num_qubits - 2) } else { 1 }; new_state_vec = execute_on_gpu(
686 state,
687 target_qubit_1, control_qubits,
689 KernelType::Swap,
690 global_work_size,
691 GpuKernelArgs::SwapTarget { q1: target_qubit_2 as i32 }, )?;
693 }
694 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
695 let updates: Vec<(usize, Complex<f64>)> = (0..dim)
697 .into_par_iter()
698 .filter_map(|i| {
699 let target_bit_1 = (i >> target_qubit_1) & 1;
700 let target_bit_2 = (i >> target_qubit_2) & 1;
701
702 if target_bit_1 != target_bit_2 {
703 let j = i ^ (1 << target_qubit_1) ^ (1 << target_qubit_2);
704 if i < j && check_controls(i, control_qubits) {
705 let amp_i = state.state_vector[i];
706 let amp_j = state.state_vector[j];
707 Some(vec![(i, amp_j), (j, amp_i)])
708 } else {
709 None
710 }
711 } else {
712 None
713 }
714 })
715 .flatten()
716 .collect();
717 for (idx, val) in updates {
718 new_state_vec[idx] = val;
719 }
720 } else {
721 for i in 0..dim {
723 let target_bit_1 = (i >> target_qubit_1) & 1;
724 let target_bit_2 = (i >> target_qubit_2) & 1;
725
726 if target_bit_1 != target_bit_2 {
727 let j = i ^ (1 << target_qubit_1) ^ (1 << target_qubit_2);
728 if i < j {
729 if check_controls(i, control_qubits) {
730 let amp_i = state.state_vector[i];
731 let amp_j = state.state_vector[j];
732 new_state_vec[i] = amp_j;
733 new_state_vec[j] = amp_i;
734 }
735 }
736 }
737 }
738 }
739
740 Ok(State {
741 state_vector: new_state_vec,
742 num_qubits: state.num_qubits(),
743 })
744 }
745
746 fn base_qubits(&self) -> usize {
747 2 }
749
750 fn to_compilable(&self) -> Option<&dyn Compilable> {
751 Some(self)
752 }
753}
754
755#[derive(Debug, Clone, Copy)]
759pub struct Toffoli;
760
761impl Operator for Toffoli {
762 fn apply(
784 &self,
785 state: &State,
786 target_qubits: &[usize],
787 control_qubits: &[usize],
788 ) -> Result<State, Error> {
789 validate_qubits(state, target_qubits, control_qubits, 1)?;
791
792 if control_qubits.len() != 2 {
794 return Err(Error::InvalidNumberOfQubits(control_qubits.len()));
795 }
796
797 if control_qubits[0] == control_qubits[1] {
799 return Err(Error::InvalidNumberOfQubits(control_qubits.len()));
800 }
801
802 Pauli::X.apply(state, target_qubits, control_qubits)
803 }
804
805 fn base_qubits(&self) -> usize {
806 3 }
808
809 fn to_compilable(&self) -> Option<&dyn Compilable> {
810 Some(self)
811 }
812}
813
814#[derive(Debug, Clone, Copy)]
818pub struct Identity;
819
820impl Operator for Identity {
821 fn apply(
835 &self,
836 state: &State,
837 target_qubits: &[usize],
838 control_qubits: &[usize],
839 ) -> Result<State, Error> {
840 validate_qubits(state, target_qubits, control_qubits, 1)?;
842
843 Ok(state.clone())
845 }
846
847 fn base_qubits(&self) -> usize {
848 1 }
850
851 fn to_compilable(&self) -> Option<&dyn Compilable> {
852 Some(self)
853 }
854}
855
856#[derive(Debug, Clone, Copy)]
860pub struct PhaseS;
861
862impl Operator for PhaseS {
863 fn apply(
877 &self,
878 state: &State,
879 target_qubits: &[usize],
880 control_qubits: &[usize],
881 ) -> Result<State, Error> {
882 validate_qubits(state, target_qubits, control_qubits, 1)?;
884
885 let target_qubit: usize = target_qubits[0];
886 let num_qubits: usize = state.num_qubits();
887
888 #[allow(unused_assignments)]
890 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
891 let gpu_enabled: bool = cfg!(feature = "gpu");
892
893 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
894 #[cfg(feature = "gpu")]
895 {
896 let global_work_size = 1 << num_qubits;
897 new_state_vec = execute_on_gpu(
898 state,
899 target_qubit,
900 control_qubits,
901 KernelType::PhaseSOrSdag,
902 global_work_size,
903 GpuKernelArgs::SOrSdag { sign: 1.0f32 },
904 )?;
905 }
906 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
907 let phase_factor = Complex::new(0.0, 1.0); new_state_vec = state.state_vector.clone(); new_state_vec
910 .par_iter_mut()
911 .enumerate()
912 .for_each(|(i, current_amp_ref)| {
913 if ((i >> target_qubit) & 1 == 1) && check_controls(i, control_qubits) {
914 *current_amp_ref = state.state_vector[i] * phase_factor;
915 }
916 });
917 } else {
918 let phase_factor = Complex::new(0.0, 1.0); new_state_vec = state.state_vector.clone(); let dim: usize = 1 << num_qubits;
921 for i in 0..dim {
922 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
923 if target_bit_is_one && check_controls(i, control_qubits) {
924 new_state_vec[i] = state.state_vector[i] * phase_factor;
925 }
926 }
927 }
928
929 Ok(State {
930 state_vector: new_state_vec,
931 num_qubits,
932 })
933 }
934
935 fn base_qubits(&self) -> usize {
936 1 }
938
939 fn to_compilable(&self) -> Option<&dyn Compilable> {
940 Some(self)
941 }
942}
943
944#[derive(Debug, Clone, Copy)]
948pub struct PhaseT;
949
950impl Operator for PhaseT {
951 fn apply(
965 &self,
966 state: &State,
967 target_qubits: &[usize],
968 control_qubits: &[usize],
969 ) -> Result<State, Error> {
970 validate_qubits(state, target_qubits, control_qubits, 1)?;
972
973 let target_qubit = target_qubits[0];
974 let num_qubits = state.num_qubits();
975
976 #[allow(unused_assignments)]
978 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
979 let gpu_enabled: bool = cfg!(feature = "gpu");
980
981 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
982 #[cfg(feature = "gpu")]
983 {
984 let global_work_size = 1 << num_qubits;
985 let angle = PI / 4.0;
986 new_state_vec = execute_on_gpu(
987 state,
988 target_qubit,
989 control_qubits,
990 KernelType::PhaseShift,
991 global_work_size,
992 GpuKernelArgs::PhaseShift {
993 cos_angle: angle.cos() as f32,
994 sin_angle: angle.sin() as f32,
995 },
996 )?;
997 }
998 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
999 let invsqrt2: f64 = 1.0 / (2.0f64).sqrt();
1000 let phase_factor = Complex::new(invsqrt2, invsqrt2); new_state_vec = state.state_vector.clone(); new_state_vec
1003 .par_iter_mut()
1004 .enumerate()
1005 .for_each(|(i, current_amp_ref)| {
1006 if ((i >> target_qubit) & 1 == 1) && check_controls(i, control_qubits) {
1007 *current_amp_ref = state.state_vector[i] * phase_factor;
1008 }
1009 });
1010 } else {
1011 let invsqrt2: f64 = 1.0 / (2.0f64).sqrt();
1012 let phase_factor = Complex::new(invsqrt2, invsqrt2); new_state_vec = state.state_vector.clone(); let dim: usize = 1 << num_qubits;
1015 for i in 0..dim {
1016 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
1017 if target_bit_is_one && check_controls(i, control_qubits) {
1018 new_state_vec[i] = state.state_vector[i] * phase_factor;
1019 }
1020 }
1021 }
1022
1023 Ok(State {
1024 state_vector: new_state_vec,
1025 num_qubits,
1026 })
1027 }
1028
1029 fn base_qubits(&self) -> usize {
1030 1 }
1032
1033 fn to_compilable(&self) -> Option<&dyn Compilable> {
1034 Some(self)
1035 }
1036}
1037
1038#[derive(Debug, Clone, Copy)]
1042pub struct PhaseSdag;
1043
1044impl Operator for PhaseSdag {
1045 fn apply(
1059 &self,
1060 state: &State,
1061 target_qubits: &[usize],
1062 control_qubits: &[usize],
1063 ) -> Result<State, Error> {
1064 validate_qubits(state, target_qubits, control_qubits, 1)?;
1066
1067 let target_qubit = target_qubits[0];
1068 let num_qubits = state.num_qubits();
1069
1070 #[allow(unused_assignments)]
1072 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
1073 let gpu_enabled: bool = cfg!(feature = "gpu");
1074
1075 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
1076 #[cfg(feature = "gpu")]
1077 {
1078 let global_work_size = 1 << num_qubits;
1079 new_state_vec = execute_on_gpu(
1080 state,
1081 target_qubit,
1082 control_qubits,
1083 KernelType::PhaseSOrSdag,
1084 global_work_size,
1085 GpuKernelArgs::SOrSdag { sign: -1.0f32 },
1086 )?;
1087 }
1088 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
1089 let phase_factor = Complex::new(0.0, -1.0); new_state_vec = state.state_vector.clone(); new_state_vec
1092 .par_iter_mut()
1093 .enumerate()
1094 .for_each(|(i, current_amp_ref)| {
1095 if ((i >> target_qubit) & 1 == 1) && check_controls(i, control_qubits) {
1096 *current_amp_ref = state.state_vector[i] * phase_factor;
1097 }
1098 });
1099 } else {
1100 let phase_factor = Complex::new(0.0, -1.0); new_state_vec = state.state_vector.clone(); let dim: usize = 1 << num_qubits;
1103 for i in 0..dim {
1104 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
1105 if target_bit_is_one && check_controls(i, control_qubits) {
1106 new_state_vec[i] = state.state_vector[i] * phase_factor;
1107 }
1108 }
1109 }
1110
1111 Ok(State {
1112 state_vector: new_state_vec,
1113 num_qubits,
1114 })
1115 }
1116
1117 fn base_qubits(&self) -> usize {
1118 1 }
1120
1121 fn to_compilable(&self) -> Option<&dyn Compilable> {
1122 Some(self)
1123 }
1124}
1125
1126#[derive(Debug, Clone, Copy)]
1130pub struct PhaseTdag;
1131
1132impl Operator for PhaseTdag {
1133 fn apply(
1147 &self,
1148 state: &State,
1149 target_qubits: &[usize],
1150 control_qubits: &[usize],
1151 ) -> Result<State, Error> {
1152 validate_qubits(state, target_qubits, control_qubits, 1)?;
1154
1155 let target_qubit = target_qubits[0];
1156 let num_qubits = state.num_qubits();
1157
1158 #[allow(unused_assignments)]
1160 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
1161 let gpu_enabled: bool = cfg!(feature = "gpu");
1162
1163 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
1164 #[cfg(feature = "gpu")]
1165 {
1166 let global_work_size = 1 << num_qubits;
1167 let angle = -PI / 4.0;
1168 new_state_vec = execute_on_gpu(
1169 state,
1170 target_qubit,
1171 control_qubits,
1172 KernelType::PhaseShift,
1173 global_work_size,
1174 GpuKernelArgs::PhaseShift {
1175 cos_angle: angle.cos() as f32,
1176 sin_angle: angle.sin() as f32,
1177 },
1178 )?;
1179 }
1180 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
1181 let invsqrt2: f64 = 1.0 / (2.0f64).sqrt();
1182 let phase_factor = Complex::new(invsqrt2, -invsqrt2);
1183 new_state_vec = state.state_vector.clone(); new_state_vec
1185 .par_iter_mut()
1186 .enumerate()
1187 .for_each(|(i, current_amp_ref)| {
1188 if ((i >> target_qubit) & 1 == 1) && check_controls(i, control_qubits) {
1189 *current_amp_ref = state.state_vector[i] * phase_factor;
1190 }
1191 });
1192 } else {
1193 let invsqrt2: f64 = 1.0 / (2.0f64).sqrt();
1194 let phase_factor = Complex::new(invsqrt2, -invsqrt2);
1195 new_state_vec = state.state_vector.clone(); let dim: usize = 1 << num_qubits;
1197 for i in 0..dim {
1198 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
1199 if target_bit_is_one && check_controls(i, control_qubits) {
1200 new_state_vec[i] = state.state_vector[i] * phase_factor;
1201 }
1202 }
1203 }
1204
1205 Ok(State {
1206 state_vector: new_state_vec,
1207 num_qubits,
1208 })
1209 }
1210
1211 fn base_qubits(&self) -> usize {
1212 1 }
1214
1215 fn to_compilable(&self) -> Option<&dyn Compilable> {
1216 Some(self)
1217 }
1218}
1219
1220#[derive(Debug, Clone, Copy)]
1224pub struct PhaseShift {
1225 pub(crate) angle: f64,
1226}
1227
1228impl PhaseShift {
1229 pub fn new(angle: f64) -> Self {
1235 PhaseShift { angle }
1236 }
1237}
1238
1239impl Operator for PhaseShift {
1240 fn apply(
1262 &self,
1263 state: &State,
1264 target_qubits: &[usize],
1265 control_qubits: &[usize],
1266 ) -> Result<State, Error> {
1267 validate_qubits(state, target_qubits, control_qubits, 1)?;
1269
1270 let target_qubit = target_qubits[0];
1271 let num_qubits = state.num_qubits();
1272
1273 #[allow(unused_assignments)]
1275 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
1276 let gpu_enabled: bool = cfg!(feature = "gpu");
1277
1278 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
1279 #[cfg(feature = "gpu")]
1280 {
1281 let global_work_size = 1 << num_qubits;
1282 new_state_vec = execute_on_gpu(
1283 state,
1284 target_qubit,
1285 control_qubits,
1286 KernelType::PhaseShift,
1287 global_work_size,
1288 GpuKernelArgs::PhaseShift {
1289 cos_angle: self.angle.cos() as f32,
1290 sin_angle: self.angle.sin() as f32,
1291 },
1292 )?;
1293 }
1294 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
1295 let phase_factor = Complex::new(self.angle.cos(), self.angle.sin());
1296 new_state_vec = state.state_vector.clone(); new_state_vec
1298 .par_iter_mut()
1299 .enumerate()
1300 .for_each(|(i, current_amp_ref)| {
1301 if ((i >> target_qubit) & 1 == 1) && check_controls(i, control_qubits) {
1302 *current_amp_ref = state.state_vector[i] * phase_factor;
1303 }
1304 });
1305 } else {
1306 let phase_factor = Complex::new(self.angle.cos(), self.angle.sin());
1307 new_state_vec = state.state_vector.clone(); let dim: usize = 1 << num_qubits;
1309 for i in 0..dim {
1310 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
1311 if target_bit_is_one && check_controls(i, control_qubits) {
1312 new_state_vec[i] = state.state_vector[i] * phase_factor;
1313 }
1314 }
1315 }
1316
1317 Ok(State {
1318 state_vector: new_state_vec,
1319 num_qubits,
1320 })
1321 }
1322
1323 fn base_qubits(&self) -> usize {
1324 1 }
1326
1327 fn to_compilable(&self) -> Option<&dyn Compilable> {
1328 Some(self)
1329 }
1330}
1331
1332#[derive(Debug, Clone, Copy)]
1336pub struct RotateX {
1337 pub(crate) angle: f64,
1338}
1339
1340impl RotateX {
1341 pub fn new(angle: f64) -> Self {
1347 RotateX { angle }
1348 }
1349}
1350
1351impl Operator for RotateX {
1352 fn apply(
1366 &self,
1367 state: &State,
1368 target_qubits: &[usize],
1369 control_qubits: &[usize],
1370 ) -> Result<State, Error> {
1371 validate_qubits(state, target_qubits, control_qubits, 1)?;
1373
1374 let target_qubit = target_qubits[0];
1375 let num_qubits = state.num_qubits();
1376
1377 #[allow(unused_assignments)]
1379 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
1380 let gpu_enabled: bool = cfg!(feature = "gpu");
1381
1382 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
1383 #[cfg(feature = "gpu")]
1384 {
1385 let half_angle = self.angle / 2.0;
1386 let global_work_size = if num_qubits > 0 { 1 << (num_qubits - 1) } else { 1 };
1387 new_state_vec = execute_on_gpu(
1388 state,
1389 target_qubit,
1390 control_qubits,
1391 KernelType::RotateX,
1392 global_work_size,
1393 GpuKernelArgs::RotationGate {
1394 cos_half_angle: half_angle.cos() as f32,
1395 sin_half_angle: half_angle.sin() as f32,
1396 },
1397 )?;
1398 }
1399 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
1400 let half_angle: f64 = self.angle / 2.0;
1402 let cos_half: f64 = half_angle.cos();
1403 let sin_half: f64 = half_angle.sin();
1404 let i_complex: Complex<f64> = Complex::new(0.0, 1.0);
1405 let dim: usize = 1 << num_qubits;
1406 new_state_vec = state.state_vector.clone(); let updates: Vec<(usize, Complex<f64>)> = (0..dim)
1409 .into_par_iter()
1410 .filter_map(|i| {
1411 if ((i >> target_qubit) & 1 == 0) && check_controls(i, control_qubits) {
1412 let j = i | (1 << target_qubit);
1413 let amp_i = state.state_vector[i];
1414 let amp_j = state.state_vector[j];
1415 Some(vec![
1416 (i, cos_half * amp_i - i_complex * sin_half * amp_j),
1417 (j, -i_complex * sin_half * amp_i + cos_half * amp_j),
1418 ])
1419 } else {
1420 None
1421 }
1422 })
1423 .flatten()
1424 .collect();
1425 for (idx, val) in updates {
1426 new_state_vec[idx] = val;
1427 }
1428 } else {
1429 let half_angle: f64 = self.angle / 2.0;
1431 let cos_half: f64 = half_angle.cos();
1432 let sin_half: f64 = half_angle.sin();
1433 let i_complex: Complex<f64> = Complex::new(0.0, 1.0);
1434 let dim: usize = 1 << num_qubits;
1435 new_state_vec = state.state_vector.clone(); for i in 0..dim {
1438 if (i >> target_qubit) & 1 == 0 {
1439 let j = i | (1 << target_qubit);
1440 if check_controls(i, control_qubits) {
1441 let amp_i = state.state_vector[i];
1442 let amp_j = state.state_vector[j];
1443 new_state_vec[i] = cos_half * amp_i - i_complex * sin_half * amp_j;
1444 new_state_vec[j] = -i_complex * sin_half * amp_i + cos_half * amp_j;
1445 }
1446 }
1447 }
1448 }
1449
1450 Ok(State {
1451 state_vector: new_state_vec,
1452 num_qubits: state.num_qubits(),
1453 })
1454 }
1455
1456 fn base_qubits(&self) -> usize {
1457 1 }
1459
1460 fn to_compilable(&self) -> Option<&dyn Compilable> {
1461 Some(self)
1462 }
1463}
1464
1465#[derive(Debug, Clone, Copy)]
1469pub struct RotateY {
1470 pub(crate) angle: f64,
1471}
1472
1473impl RotateY {
1474 pub fn new(angle: f64) -> Self {
1480 RotateY { angle }
1481 }
1482}
1483
1484impl Operator for RotateY {
1485 fn apply(
1499 &self,
1500 state: &State,
1501 target_qubits: &[usize],
1502 control_qubits: &[usize],
1503 ) -> Result<State, Error> {
1504 validate_qubits(state, target_qubits, control_qubits, 1)?;
1506
1507 let target_qubit = target_qubits[0];
1508 let num_qubits = state.num_qubits();
1509
1510 #[allow(unused_assignments)]
1512 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
1513 let gpu_enabled: bool = cfg!(feature = "gpu");
1514
1515 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
1516 #[cfg(feature = "gpu")]
1517 {
1518 let half_angle = self.angle / 2.0;
1519 let global_work_size = if num_qubits > 0 { 1 << (num_qubits - 1) } else { 1 };
1520 new_state_vec = execute_on_gpu(
1521 state,
1522 target_qubit,
1523 control_qubits,
1524 KernelType::RotateY,
1525 global_work_size,
1526 GpuKernelArgs::RotationGate {
1527 cos_half_angle: half_angle.cos() as f32,
1528 sin_half_angle: half_angle.sin() as f32,
1529 },
1530 )?;
1531 }
1532 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
1533 let half_angle: f64 = self.angle / 2.0;
1535 let cos_half: f64 = half_angle.cos();
1536 let sin_half: f64 = half_angle.sin();
1537 let dim: usize = 1 << num_qubits;
1538 new_state_vec = state.state_vector.clone(); let updates: Vec<(usize, Complex<f64>)> = (0..dim)
1541 .into_par_iter()
1542 .filter_map(|i| {
1543 if ((i >> target_qubit) & 1 == 0) && check_controls(i, control_qubits) {
1544 let j = i | (1 << target_qubit);
1545 let amp_i = state.state_vector[i];
1546 let amp_j = state.state_vector[j];
1547 Some(vec![
1548 (i, cos_half * amp_i - sin_half * amp_j),
1549 (j, sin_half * amp_i + cos_half * amp_j),
1550 ])
1551 } else {
1552 None
1553 }
1554 })
1555 .flatten()
1556 .collect();
1557 for (idx, val) in updates {
1558 new_state_vec[idx] = val;
1559 }
1560 } else {
1561 let half_angle: f64 = self.angle / 2.0;
1563 let cos_half: f64 = half_angle.cos();
1564 let sin_half: f64 = half_angle.sin();
1565 let dim: usize = 1 << num_qubits;
1566 new_state_vec = state.state_vector.clone(); for i in 0..dim {
1569 if (i >> target_qubit) & 1 == 0 {
1570 let j = i | (1 << target_qubit);
1571 if check_controls(i, control_qubits) {
1572 let amp_i = state.state_vector[i];
1573 let amp_j = state.state_vector[j];
1574 new_state_vec[i] = cos_half * amp_i - sin_half * amp_j;
1575 new_state_vec[j] = sin_half * amp_i + cos_half * amp_j;
1576 }
1577 }
1578 }
1579 }
1580
1581 Ok(State {
1582 state_vector: new_state_vec,
1583 num_qubits: state.num_qubits(),
1584 })
1585 }
1586
1587 fn base_qubits(&self) -> usize {
1588 1 }
1590
1591 fn to_compilable(&self) -> Option<&dyn Compilable> {
1592 Some(self)
1593 }
1594}
1595
1596#[derive(Debug, Clone, Copy)]
1600pub struct RotateZ {
1601 pub(crate) angle: f64,
1602}
1603
1604impl RotateZ {
1605 pub fn new(angle: f64) -> Self {
1611 RotateZ { angle }
1612 }
1613}
1614
1615impl Operator for RotateZ {
1616 fn apply(
1630 &self,
1631 state: &State,
1632 target_qubits: &[usize],
1633 control_qubits: &[usize],
1634 ) -> Result<State, Error> {
1635 validate_qubits(state, target_qubits, control_qubits, 1)?;
1637
1638 let target_qubit = target_qubits[0];
1639 let num_qubits = state.num_qubits();
1640
1641 #[allow(unused_assignments)]
1643 let mut new_state_vec: Vec<Complex<f64>> = state.state_vector.clone();
1644 let gpu_enabled: bool = cfg!(feature = "gpu");
1645
1646 if num_qubits >= OPENCL_THRESHOLD_NUM_QUBITS && gpu_enabled {
1647 #[cfg(feature = "gpu")]
1648 {
1649 let half_angle = self.angle / 2.0;
1650 let global_work_size = 1 << num_qubits; new_state_vec = execute_on_gpu(
1652 state,
1653 target_qubit,
1654 control_qubits,
1655 KernelType::RotateZ,
1656 global_work_size,
1657 GpuKernelArgs::RotationGate {
1658 cos_half_angle: half_angle.cos() as f32,
1659 sin_half_angle: half_angle.sin() as f32,
1660 },
1661 )?;
1662 }
1663 } else if num_qubits >= PARALLEL_THRESHOLD_NUM_QUBITS {
1664 let half_angle = self.angle / 2.0;
1666 let phase_0 = Complex::new(half_angle.cos(), -half_angle.sin());
1667 let phase_1 = Complex::new(half_angle.cos(), half_angle.sin());
1668 new_state_vec = state.state_vector.clone(); new_state_vec
1671 .par_iter_mut()
1672 .enumerate()
1673 .for_each(|(i, current_amp_ref)| {
1674 if check_controls(i, control_qubits) {
1675 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
1676 if target_bit_is_one {
1677 *current_amp_ref = state.state_vector[i] * phase_1;
1678 } else {
1679 *current_amp_ref = state.state_vector[i] * phase_0;
1680 }
1681 }
1682 });
1683 } else {
1684 let half_angle = self.angle / 2.0;
1686 let phase_0 = Complex::new(half_angle.cos(), -half_angle.sin());
1687 let phase_1 = Complex::new(half_angle.cos(), half_angle.sin());
1688 let dim: usize = 1 << num_qubits;
1689 new_state_vec = state.state_vector.clone(); for i in 0..dim {
1692 if check_controls(i, control_qubits) {
1693 let target_bit_is_one = (i >> target_qubit) & 1 == 1;
1694 if target_bit_is_one {
1695 new_state_vec[i] = state.state_vector[i] * phase_1;
1696 } else {
1697 new_state_vec[i] = state.state_vector[i] * phase_0;
1698 }
1699 }
1700 }
1701 }
1702
1703 Ok(State {
1704 state_vector: new_state_vec,
1705 num_qubits: state.num_qubits(),
1706 })
1707 }
1708
1709 fn base_qubits(&self) -> usize {
1710 1 }
1712
1713 fn to_compilable(&self) -> Option<&dyn Compilable> {
1714 Some(self)
1715 }
1716}
1717
1718#[derive(Debug, Clone, Copy)]
1722pub struct Unitary2 {
1723 pub(crate) matrix: [[Complex<f64>; 2]; 2],
1725}
1726
1727impl Unitary2 {
1728 pub fn new(matrix: [[Complex<f64>; 2]; 2]) -> Result<Self, Error> {
1742 let tol: f64 = f64::EPSILON * 2.0; let a: Complex<f64> = matrix[0][0]; let b: Complex<f64> = matrix[0][1]; let c: Complex<f64> = matrix[1][0]; let d: Complex<f64> = matrix[1][1]; if ((a.norm_sqr() + b.norm_sqr()) - 1.0).abs() > tol {
1752 return Err(Error::NonUnitaryMatrix);
1753 }
1754 if ((c.norm_sqr() + d.norm_sqr()) - 1.0).abs() > tol {
1756 return Err(Error::NonUnitaryMatrix);
1757 }
1758
1759 if (a * c.conj() + b * d.conj()).norm_sqr() > tol * tol {
1762 return Err(Error::NonUnitaryMatrix);
1764 }
1765
1766 Ok(Unitary2 { matrix })
1767 }
1768}
1769
1770impl Operator for Unitary2 {
1771 fn apply(
1785 &self,
1786 state: &State,
1787 target_qubits: &[usize],
1788 control_qubits: &[usize],
1789 ) -> Result<State, Error> {
1790 validate_qubits(state, target_qubits, control_qubits, 1)?;
1792
1793 let t: usize = target_qubits[0];
1794 let nq: usize = state.num_qubits();
1795
1796 let dim = 1 << nq;
1798 let mut new_state_vec = state.state_vector.clone();
1799
1800 if nq >= PARALLEL_THRESHOLD_NUM_QUBITS {
1801 let updates: Vec<(usize, Complex<f64>)> = (0..dim)
1803 .into_par_iter()
1804 .filter_map(|i| {
1805 if ((i >> t) & 1 == 0) && check_controls(i, control_qubits) {
1806 let j = i | (1 << t);
1807 let ai = state.state_vector[i];
1808 let aj = state.state_vector[j];
1809 Some(vec![
1810 (i, self.matrix[0][0] * ai + self.matrix[0][1] * aj),
1811 (j, self.matrix[1][0] * ai + self.matrix[1][1] * aj),
1812 ])
1813 } else {
1814 None
1815 }
1816 })
1817 .flatten()
1818 .collect();
1819 for (idx, val) in updates {
1820 new_state_vec[idx] = val;
1821 }
1822 } else {
1823 for i in 0..dim {
1825 if (i >> t) & 1 == 0 {
1826 let j = i | (1 << t);
1827 if check_controls(i, control_qubits) {
1828 let ai = state.state_vector[i];
1829 let aj = state.state_vector[j];
1830 new_state_vec[i] = self.matrix[0][0] * ai + self.matrix[0][1] * aj;
1831 new_state_vec[j] = self.matrix[1][0] * ai + self.matrix[1][1] * aj;
1832 }
1833 }
1834 }
1835 }
1836
1837 Ok(State {
1838 state_vector: new_state_vec,
1839 num_qubits: nq,
1840 })
1841 }
1842
1843 fn base_qubits(&self) -> usize {
1844 1
1845 }
1846
1847 fn to_compilable(&self) -> Option<&dyn Compilable> {
1848 Some(self)
1849 }
1850}