1use scirs2_core::ndarray::{Array1, Array2};
2use scirs2_core::parallel_ops::{
3 IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator,
4};
5use scirs2_core::Complex64;
6
7use quantrs2_core::qubit::QubitId;
8
9#[must_use]
11pub fn kron(a: &Array2<Complex64>, b: &Array2<Complex64>) -> Array2<Complex64> {
12 let a_shape = a.shape();
13 let b_shape = b.shape();
14
15 let rows = a_shape[0] * b_shape[0];
16 let cols = a_shape[1] * b_shape[1];
17
18 let mut result = Array2::zeros((rows, cols));
19
20 for i in 0..a_shape[0] {
21 for j in 0..a_shape[1] {
22 let a_val = a[[i, j]];
23 let i_offset = i * b_shape[0];
24 let j_offset = j * b_shape[1];
25
26 for k in 0..b_shape[0] {
27 for l in 0..b_shape[1] {
28 result[[i_offset + k, j_offset + l]] = a_val * b[[k, l]];
29 }
30 }
31 }
32 }
33
34 result
35}
36
37#[must_use]
39pub fn tensor_product(a: &Array1<Complex64>, b: &Array1<Complex64>) -> Array1<Complex64> {
40 let a_len = a.len();
41 let b_len = b.len();
42 let result_len = a_len * b_len;
43
44 let mut result = Array1::zeros(result_len);
45
46 for i in 0..a_len {
47 let a_val = a[i];
48 let offset = i * b_len;
49
50 for j in 0..b_len {
51 result[offset + j] = a_val * b[j];
52 }
53 }
54
55 result
56}
57
58#[must_use]
60pub fn int_to_bits(n: usize, num_bits: usize) -> Vec<u8> {
61 let mut bits = vec![0; num_bits];
62 for i in 0..num_bits {
63 bits[num_bits - 1 - i] = ((n >> i) & 1) as u8;
64 }
65 bits
66}
67
68#[must_use]
70pub fn bits_to_int(bits: &[u8]) -> usize {
71 bits.iter().fold(0, |acc, &bit| (acc << 1) | bit as usize)
72}
73
74#[must_use]
76pub const fn flip_bit(index: usize, pos: usize) -> usize {
77 index ^ (1 << pos)
78}
79
80#[must_use]
84pub const fn controlled_flip(index: usize, ctrl_pos: usize, target_pos: usize) -> usize {
85 if (index >> ctrl_pos) & 1 == 1 {
86 flip_bit(index, target_pos)
87 } else {
88 index
89 }
90}
91
92#[must_use]
96pub fn compute_index(qubit_indices: &[QubitId], state_bits: &[u8]) -> usize {
97 assert!(
98 (qubit_indices.len() == state_bits.len()),
99 "Mismatch between qubit indices and state bits"
100 );
101
102 let mut index = 0;
103 for (&qubit, &bit) in qubit_indices.iter().zip(state_bits.iter()) {
104 let q = qubit.id() as usize;
105 if bit != 0 {
106 index |= 1 << q;
107 }
108 }
109
110 index
111}
112
113pub fn par_indexed_map<F>(state: &mut [Complex64], f: F)
118where
119 F: Fn(usize, Complex64) -> Complex64 + Sync,
120{
121 state.par_iter_mut().enumerate().for_each(|(i, v)| {
122 *v = f(i, *v);
123 });
124}
125
126#[must_use]
128pub fn gate_vec_to_array2(matrix: &[Complex64], dim: usize) -> Array2<Complex64> {
129 let mut result = Array2::zeros((dim, dim));
130
131 for i in 0..dim {
132 for j in 0..dim {
133 result[[i, j]] = matrix[i * dim + j];
134 }
135 }
136
137 result
138}