1use crate::error::QuantRS2Result;
7use scirs2_core::Complex64;
8use crate::simd_ops_stubs::{SimdComplex64, SimdF64};
10use scirs2_core::ndarray::{ArrayView1, ArrayViewMut1};
11
12pub fn apply_phase_simd(amplitudes: &mut [Complex64], theta: f64) {
18 let cos_theta = theta.cos();
19 let sin_theta = theta.sin();
20
21 let len = amplitudes.len();
23 let mut real_parts = Vec::with_capacity(len);
24 let mut imag_parts = Vec::with_capacity(len);
25
26 for amp in amplitudes.iter() {
27 real_parts.push(amp.re);
28 imag_parts.push(amp.im);
29 }
30
31 let mut new_real = vec![0.0; len];
34 let mut new_imag = vec![0.0; len];
35
36 let real_view = ArrayView1::from(&real_parts);
38 let imag_view = ArrayView1::from(&imag_parts);
39 let mut new_real_view = ArrayViewMut1::from(&mut new_real);
40 let mut new_imag_view = ArrayViewMut1::from(&mut new_imag);
41
42 let real_cos = <f64 as SimdF64>::simd_scalar_mul(&real_view, cos_theta);
44 let imag_sin = <f64 as SimdF64>::simd_scalar_mul(&imag_view, sin_theta);
45 let new_real_arr = <f64 as SimdF64>::simd_sub_arrays(&real_cos.view(), &imag_sin.view());
46
47 let real_sin = <f64 as SimdF64>::simd_scalar_mul(&real_view, sin_theta);
49 let imag_cos = <f64 as SimdF64>::simd_scalar_mul(&imag_view, cos_theta);
50 let new_imag_arr = <f64 as SimdF64>::simd_add_arrays(&real_sin.view(), &imag_cos.view());
51
52 new_real_view.assign(&new_real_arr);
54 new_imag_view.assign(&new_imag_arr);
55
56 for (i, amp) in amplitudes.iter_mut().enumerate() {
58 *amp = Complex64::new(new_real[i], new_imag[i]);
59 }
60}
61
62pub fn inner_product(state1: &[Complex64], state2: &[Complex64]) -> QuantRS2Result<Complex64> {
66 if state1.len() != state2.len() {
67 return Err(crate::error::QuantRS2Error::InvalidInput(
68 "State vectors must have the same length".to_string(),
69 ));
70 }
71
72 let len = state1.len();
73
74 let mut state1_real = Vec::with_capacity(len);
76 let mut state1_imag = Vec::with_capacity(len);
77 let mut state2_real = Vec::with_capacity(len);
78 let mut state2_imag = Vec::with_capacity(len);
79
80 for (a, b) in state1.iter().zip(state2.iter()) {
81 state1_real.push(a.re);
82 state1_imag.push(a.im);
83 state2_real.push(b.re);
84 state2_imag.push(b.im);
85 }
86
87 let state1_real_view = ArrayView1::from(&state1_real);
92 let state1_imag_view = ArrayView1::from(&state1_imag);
93 let state2_real_view = ArrayView1::from(&state2_real);
94 let state2_imag_view = ArrayView1::from(&state2_imag);
95
96 let rr_product = <f64 as SimdF64>::simd_mul_arrays(&state1_real_view, &state2_real_view);
98 let ii_product = <f64 as SimdF64>::simd_mul_arrays(&state1_imag_view, &state2_imag_view);
99 let real_sum = <f64 as SimdF64>::simd_add_arrays(&rr_product.view(), &ii_product.view());
100 let real_part = <f64 as SimdF64>::simd_sum_array(&real_sum.view());
101
102 let ri_product = <f64 as SimdF64>::simd_mul_arrays(&state1_real_view, &state2_imag_view);
104 let ir_product = <f64 as SimdF64>::simd_mul_arrays(&state1_imag_view, &state2_real_view);
105 let imag_diff = <f64 as SimdF64>::simd_sub_arrays(&ri_product.view(), &ir_product.view());
106 let imag_part = <f64 as SimdF64>::simd_sum_array(&imag_diff.view());
107
108 Ok(Complex64::new(real_part, -imag_part)) }
110
111pub fn normalize_simd(amplitudes: &mut [Complex64]) -> QuantRS2Result<()> {
115 let len = amplitudes.len();
116
117 let mut real_parts = Vec::with_capacity(len);
119 let mut imag_parts = Vec::with_capacity(len);
120
121 for amp in amplitudes.iter() {
122 real_parts.push(amp.re);
123 imag_parts.push(amp.im);
124 }
125
126 let real_view = ArrayView1::from(&real_parts);
128 let imag_view = ArrayView1::from(&imag_parts);
129
130 let real_squared = <f64 as SimdF64>::simd_mul_arrays(&real_view, &real_view);
131 let imag_squared = <f64 as SimdF64>::simd_mul_arrays(&imag_view, &imag_view);
132 let sum_squared = <f64 as SimdF64>::simd_add_arrays(&real_squared.view(), &imag_squared.view());
133
134 let norm_sqr = <f64 as SimdF64>::simd_sum_array(&sum_squared.view());
135
136 if norm_sqr == 0.0 {
137 return Err(crate::error::QuantRS2Error::InvalidInput(
138 "Cannot normalize zero vector".to_string(),
139 ));
140 }
141
142 let norm = norm_sqr.sqrt();
143 let norm_inv = 1.0 / norm;
144
145 let mut normalized_real = vec![0.0; len];
147 let mut normalized_imag = vec![0.0; len];
148 let mut normalized_real_view = ArrayViewMut1::from(&mut normalized_real);
149 let mut normalized_imag_view = ArrayViewMut1::from(&mut normalized_imag);
150
151 let normalized_real_arr = <f64 as SimdF64>::simd_scalar_mul(&real_view, norm_inv);
152 let normalized_imag_arr = <f64 as SimdF64>::simd_scalar_mul(&imag_view, norm_inv);
153 normalized_real_view.assign(&normalized_real_arr);
154 normalized_imag_view.assign(&normalized_imag_arr);
155
156 for (i, amp) in amplitudes.iter_mut().enumerate() {
158 *amp = Complex64::new(normalized_real[i], normalized_imag[i]);
159 }
160
161 Ok(())
162}
163
164pub fn expectation_z_simd(amplitudes: &[Complex64], qubit: usize, _num_qubits: usize) -> f64 {
168 let qubit_mask = 1 << qubit;
169 let len = amplitudes.len();
170
171 let mut norm_sqrs = Vec::with_capacity(len);
173 let mut signs = Vec::with_capacity(len);
174
175 for (i, amp) in amplitudes.iter().enumerate() {
176 norm_sqrs.push(amp.re * amp.re + amp.im * amp.im);
177 signs.push(if (i & qubit_mask) == 0 { 1.0 } else { -1.0 });
178 }
179
180 let norm_view = ArrayView1::from(&norm_sqrs);
182 let sign_view = ArrayView1::from(&signs);
183
184 let weighted_arr = <f64 as SimdF64>::simd_mul_arrays(&norm_view, &sign_view);
185 <f64 as SimdF64>::simd_sum_array(&weighted_arr.view())
186}
187
188pub fn hadamard_simd(amplitudes: &mut [Complex64], qubit: usize, _num_qubits: usize) {
192 let qubit_mask = 1 << qubit;
193 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
194
195 let mut idx0_list = Vec::new();
197 let mut idx1_list = Vec::new();
198
199 for i in 0..(amplitudes.len() / 2) {
200 let idx0 = (i & !(qubit_mask >> 1)) | ((i & (qubit_mask >> 1)) << 1);
201 let idx1 = idx0 | qubit_mask;
202
203 if idx1 < amplitudes.len() {
204 idx0_list.push(idx0);
205 idx1_list.push(idx1);
206 }
207 }
208
209 let pair_count = idx0_list.len();
210 if pair_count == 0 {
211 return;
212 }
213
214 let mut a0_real = Vec::with_capacity(pair_count);
216 let mut a0_imag = Vec::with_capacity(pair_count);
217 let mut a1_real = Vec::with_capacity(pair_count);
218 let mut a1_imag = Vec::with_capacity(pair_count);
219
220 for i in 0..pair_count {
221 let a0 = amplitudes[idx0_list[i]];
222 let a1 = amplitudes[idx1_list[i]];
223 a0_real.push(a0.re);
224 a0_imag.push(a0.im);
225 a1_real.push(a1.re);
226 a1_imag.push(a1.im);
227 }
228
229 let a0_real_view = ArrayView1::from(&a0_real);
231 let a0_imag_view = ArrayView1::from(&a0_imag);
232 let a1_real_view = ArrayView1::from(&a1_real);
233 let a1_imag_view = ArrayView1::from(&a1_imag);
234
235 let mut new_a0_real = vec![0.0; pair_count];
236 let mut new_a0_imag = vec![0.0; pair_count];
237 let mut new_a1_real = vec![0.0; pair_count];
238 let mut new_a1_imag = vec![0.0; pair_count];
239
240 let mut new_a0_real_view = ArrayViewMut1::from(&mut new_a0_real);
241 let mut new_a0_imag_view = ArrayViewMut1::from(&mut new_a0_imag);
242 let mut new_a1_real_view = ArrayViewMut1::from(&mut new_a1_real);
243 let mut new_a1_imag_view = ArrayViewMut1::from(&mut new_a1_imag);
244
245 let real_sum = <f64 as SimdF64>::simd_add_arrays(&a0_real_view, &a1_real_view);
247 let new_a0_real_arr = <f64 as SimdF64>::simd_scalar_mul(&real_sum.view(), sqrt2_inv);
248 let imag_sum = <f64 as SimdF64>::simd_add_arrays(&a0_imag_view, &a1_imag_view);
249 let new_a0_imag_arr = <f64 as SimdF64>::simd_scalar_mul(&imag_sum.view(), sqrt2_inv);
250
251 let real_diff = <f64 as SimdF64>::simd_sub_arrays(&a0_real_view, &a1_real_view);
253 let new_a1_real_arr = <f64 as SimdF64>::simd_scalar_mul(&real_diff.view(), sqrt2_inv);
254 let imag_diff = <f64 as SimdF64>::simd_sub_arrays(&a0_imag_view, &a1_imag_view);
255 let new_a1_imag_arr = <f64 as SimdF64>::simd_scalar_mul(&imag_diff.view(), sqrt2_inv);
256
257 new_a0_real_view.assign(&new_a0_real_arr);
258 new_a0_imag_view.assign(&new_a0_imag_arr);
259 new_a1_real_view.assign(&new_a1_real_arr);
260 new_a1_imag_view.assign(&new_a1_imag_arr);
261
262 for i in 0..pair_count {
264 amplitudes[idx0_list[i]] = Complex64::new(new_a0_real[i], new_a0_imag[i]);
265 amplitudes[idx1_list[i]] = Complex64::new(new_a1_real[i], new_a1_imag[i]);
266 }
267}
268
269pub fn controlled_phase_simd(
273 amplitudes: &mut [Complex64],
274 control_qubit: usize,
275 target_qubit: usize,
276 theta: f64,
277) -> QuantRS2Result<()> {
278 let num_qubits = (amplitudes.len() as f64).log2() as usize;
279
280 if control_qubit >= num_qubits || target_qubit >= num_qubits {
281 return Err(crate::error::QuantRS2Error::InvalidInput(
282 "Qubit index out of range".to_string(),
283 ));
284 }
285
286 let cos_theta = theta.cos();
287 let sin_theta = theta.sin();
288 let control_mask = 1 << control_qubit;
289 let target_mask = 1 << target_qubit;
290
291 let mut indices = Vec::new();
293 for idx in 0..amplitudes.len() {
294 if (idx & control_mask) != 0 && (idx & target_mask) != 0 {
295 indices.push(idx);
296 }
297 }
298
299 if indices.is_empty() {
300 return Ok(());
301 }
302
303 let count = indices.len();
305 let mut real_parts = Vec::with_capacity(count);
306 let mut imag_parts = Vec::with_capacity(count);
307
308 for &idx in &indices {
309 let amp = amplitudes[idx];
310 real_parts.push(amp.re);
311 imag_parts.push(amp.im);
312 }
313
314 let real_view = ArrayView1::from(&real_parts);
316 let imag_view = ArrayView1::from(&imag_parts);
317
318 let mut new_real = vec![0.0; count];
319 let mut new_imag = vec![0.0; count];
320 let mut new_real_view = ArrayViewMut1::from(&mut new_real);
321 let mut new_imag_view = ArrayViewMut1::from(&mut new_imag);
322
323 let real_cos = <f64 as SimdF64>::simd_scalar_mul(&real_view, cos_theta);
325 let imag_sin = <f64 as SimdF64>::simd_scalar_mul(&imag_view, sin_theta);
326 let new_real_arr = <f64 as SimdF64>::simd_sub_arrays(&real_cos.view(), &imag_sin.view());
327
328 let real_sin = <f64 as SimdF64>::simd_scalar_mul(&real_view, sin_theta);
330 let imag_cos = <f64 as SimdF64>::simd_scalar_mul(&imag_view, cos_theta);
331 let new_imag_arr = <f64 as SimdF64>::simd_add_arrays(&real_sin.view(), &imag_cos.view());
332
333 new_real_view.assign(&new_real_arr);
334 new_imag_view.assign(&new_imag_arr);
335
336 for (i, &idx) in indices.iter().enumerate() {
338 amplitudes[idx] = Complex64::new(new_real[i], new_imag[i]);
339 }
340
341 Ok(())
342}
343
344#[cfg(test)]
345mod tests {
346 use super::*;
347
348 #[test]
349 fn test_normalize_simd() {
350 let mut state = vec![
351 Complex64::new(1.0, 0.0),
352 Complex64::new(0.0, 1.0),
353 Complex64::new(1.0, 0.0),
354 Complex64::new(0.0, -1.0),
355 ];
356
357 normalize_simd(&mut state).unwrap();
358
359 let norm_sqr: f64 = state.iter().map(|c| c.norm_sqr()).sum();
360 assert!((norm_sqr - 1.0).abs() < 1e-10);
361 }
362
363 #[test]
364 fn test_inner_product() {
365 let state1 = vec![Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)];
366 let state2 = vec![Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0)];
367
368 let result = inner_product(&state1, &state2).unwrap();
369 assert_eq!(result, Complex64::new(0.0, 0.0));
370 }
371
372 #[test]
373 fn test_expectation_z() {
374 let state0 = vec![Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)];
376 let exp0 = expectation_z_simd(&state0, 0, 1);
377 assert!((exp0 - 1.0).abs() < 1e-10);
378
379 let state1 = vec![Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0)];
381 let exp1 = expectation_z_simd(&state1, 0, 1);
382 assert!((exp1 + 1.0).abs() < 1e-10);
383
384 let sqrt2_inv = 1.0 / std::f64::consts::SQRT_2;
386 let state_plus = vec![
387 Complex64::new(sqrt2_inv, 0.0),
388 Complex64::new(sqrt2_inv, 0.0),
389 ];
390 let exp_plus = expectation_z_simd(&state_plus, 0, 1);
391 assert!(exp_plus.abs() < 1e-10);
392 }
393
394 #[test]
395 fn test_hadamard_simd() {
396 let mut state = vec![Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)];
398 hadamard_simd(&mut state, 0, 1);
399
400 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
401 assert!((state[0].re - sqrt2_inv).abs() < 1e-10);
402 assert!((state[1].re - sqrt2_inv).abs() < 1e-10);
403 assert!(state[0].im.abs() < 1e-10);
404 assert!(state[1].im.abs() < 1e-10);
405
406 hadamard_simd(&mut state, 0, 1);
408 assert!((state[0].re - 1.0).abs() < 1e-10);
409 assert!(state[1].re.abs() < 1e-10);
410 }
411
412 #[test]
413 fn test_phase_simd() {
414 let mut state = vec![Complex64::new(0.5, 0.5), Complex64::new(0.5, -0.5)];
415
416 let theta = std::f64::consts::PI / 4.0;
417 apply_phase_simd(&mut state, theta);
418
419 let norm_before = 0.5_f64.powi(2) + 0.5_f64.powi(2);
421 let norm_after = state[0].norm_sqr();
422 assert!((norm_before - norm_after).abs() < 1e-10);
423 }
424}