26 #include <immintrin.h> 70 unsigned int bitmask_high = ~bitmask_low;
74 if ( control_qbit == 0 ) {
76 for (
int idx=0; idx<matrix_size/2; idx++ ) {
79 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
82 int current_idx_pair = current_idx | (1<<
target_qbit);
84 if ( current_idx & control_qbit_step_index ) {
93 input[current_idx].real = tmp1.
real + tmp2.
real;
94 input[current_idx].imag = tmp1.
imag + tmp2.
imag;
99 input[current_idx_pair].real = tmp3.
real + tmp4.
real;
100 input[current_idx_pair].imag = tmp3.
imag + tmp4.
imag;
119 else if ( target_qbit == 0 ) {
139 __m256d mv00 = _mm256_set_pd(-u3_1qbit[1].imag, u3_1qbit[1].
real, -u3_1qbit[0].imag, u3_1qbit[0].real);
140 __m256d mv01 = _mm256_set_pd( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
141 __m256d mv20 = _mm256_set_pd(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
142 __m256d mv21 = _mm256_set_pd( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
144 for (
int idx=0; idx<matrix_size/2; idx++ ) {
147 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
149 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
152 double *ptr = (
double*)input.
get_data() + 2 * current_idx;
153 __m256d
data = _mm256_loadu_pd(ptr);
155 __m256d data_u0 = _mm256_mul_pd(data, mv00);
156 __m256d data_u1 = _mm256_mul_pd(data, mv01);
157 __m256d data_u2 = _mm256_hadd_pd(data_u0, data_u1);
158 data_u2 = _mm256_permute4x64_pd(data_u2, 216);
160 __m256d data_d0 = _mm256_mul_pd(data, mv20);
161 __m256d data_d1 = _mm256_mul_pd(data, mv21);
162 __m256d data_d2 = _mm256_hadd_pd(data_d0, data_d1);
163 data_d2 = _mm256_permute4x64_pd(data_d2, 216);
165 __m256d data_r = _mm256_hadd_pd(data_u2, data_d2);
167 data_r = _mm256_permute4x64_pd(data_r, 216);
168 _mm256_storeu_pd(ptr, data_r);
205 __m256d mv00 = _mm256_set_pd(-u3_1qbit[0].imag, u3_1qbit[0].
real, -u3_1qbit[0].imag, u3_1qbit[0].real);
206 __m256d mv01 = _mm256_set_pd( u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
207 __m256d mv10 = _mm256_set_pd(-u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real);
208 __m256d mv11 = _mm256_set_pd( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag);
209 __m256d mv20 = _mm256_set_pd(-u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
210 __m256d mv21 = _mm256_set_pd( u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
211 __m256d mv30 = _mm256_set_pd(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real);
212 __m256d mv31 = _mm256_set_pd( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag);
215 for (
int idx=0; idx<matrix_size/2; idx=idx+2 ) {
218 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
221 int current_idx_pair = current_idx | (1<<
target_qbit);
223 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
226 double* element = (
double*)input.
get_data() + 2 * current_idx;
227 double* element_pair = (
double*)input.
get_data() + 2 * current_idx_pair;
230 __m256d data0 = _mm256_loadu_pd(element);
231 __m256d data1 = _mm256_loadu_pd(element_pair);
233 __m256d data_u2 = _mm256_mul_pd(data0, mv00);
234 __m256d data_u3 = _mm256_mul_pd(data1, mv10);
235 __m256d data_u4 = _mm256_mul_pd(data0, mv01);
236 __m256d data_u5 = _mm256_mul_pd(data1, mv11);
238 __m256d data_u6 = _mm256_hadd_pd(data_u2, data_u4);
239 __m256d data_u7 = _mm256_hadd_pd(data_u3, data_u5);
241 __m256d data_d2 = _mm256_mul_pd(data0, mv20);
242 __m256d data_d3 = _mm256_mul_pd(data1, mv30);
243 __m256d data_d4 = _mm256_mul_pd(data0, mv21);
244 __m256d data_d5 = _mm256_mul_pd(data1, mv31);
246 __m256d data_d6 = _mm256_hadd_pd(data_d2, data_d4);
247 __m256d data_d7 = _mm256_hadd_pd(data_d3, data_d5);
249 __m256d data_r0 = _mm256_add_pd(data_u6, data_u7);
250 __m256d data_r1 = _mm256_add_pd(data_d6, data_d7);
252 _mm256_storeu_pd(element, data_r0);
253 _mm256_storeu_pd(element_pair, data_r1);
286 unsigned int bitmask_high = ~bitmask_low;
290 if ( control_qbit == 0 ) {
292 for (
int idx=0; idx<matrix_size/2; idx++ ) {
295 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
298 int current_idx_pair = current_idx | (1<<
target_qbit);
300 if ( current_idx & control_qbit_step_index ) {
309 input[current_idx].real = tmp1.
real + tmp2.
real;
310 input[current_idx].imag = tmp1.
imag + tmp2.
imag;
315 input[current_idx_pair].real = tmp3.
real + tmp4.
real;
316 input[current_idx_pair].imag = tmp3.
imag + tmp4.
imag;
335 else if ( target_qbit == 0 ) {
355 __m256 mv00 = _mm256_set_ps(-u3_1qbit[1].imag, u3_1qbit[1].
real, -u3_1qbit[0].imag, u3_1qbit[0].real,
356 -u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[0].imag, u3_1qbit[0].real);
357 __m256 mv01 = _mm256_set_ps( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag,
358 u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
359 __m256 mv20 = _mm256_set_ps(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real,
360 -u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
361 __m256 mv21 = _mm256_set_ps( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag,
362 u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
364 for (
int idx=0; idx<matrix_size/2; idx++ ) {
367 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
369 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
372 float *ptr = (
float*)input.
get_data() + 2 * current_idx;
373 __m128 data_low = _mm_loadu_ps(ptr);
374 __m256
data = _mm256_castps128_ps256(data_low);
375 data = _mm256_insertf128_ps(data, data_low, 1);
377 __m256 data_u0 = _mm256_mul_ps(data, mv00);
378 __m256 data_u1 = _mm256_mul_ps(data, mv01);
379 __m256 data_u2 = _mm256_hadd_ps(data_u0, data_u1);
380 data_u2 = _mm256_permutevar8x32_ps(data_u2, _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7));
382 __m256 data_d0 = _mm256_mul_ps(data, mv20);
383 __m256 data_d1 = _mm256_mul_ps(data, mv21);
384 __m256 data_d2 = _mm256_hadd_ps(data_d0, data_d1);
385 data_d2 = _mm256_permutevar8x32_ps(data_d2, _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7));
387 __m256 data_r = _mm256_hadd_ps(data_u2, data_d2);
389 data_r = _mm256_permutevar8x32_ps(data_r, _mm256_setr_epi32(0, 4, 2, 6, 1, 5, 3, 7));
390 _mm_storeu_ps(ptr, _mm256_castps256_ps128(data_r));
427 __m256 mv00 = _mm256_set_ps(-u3_1qbit[0].imag, u3_1qbit[0].
real, -u3_1qbit[0].imag, u3_1qbit[0].real,
428 -u3_1qbit[0].imag, u3_1qbit[0].real, -u3_1qbit[0].imag, u3_1qbit[0].real);
429 __m256 mv01 = _mm256_set_ps( u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag,
430 u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
431 __m256 mv10 = _mm256_set_ps(-u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real,
432 -u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real);
433 __m256 mv11 = _mm256_set_ps( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag,
434 u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag);
435 __m256 mv20 = _mm256_set_ps(-u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real,
436 -u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
437 __m256 mv21 = _mm256_set_ps( u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag,
438 u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
439 __m256 mv30 = _mm256_set_ps(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real,
440 -u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real);
441 __m256 mv31 = _mm256_set_ps( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag,
442 u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag);
445 if ( target_qbit == 1 ) {
448 for (
int idx=0; idx<matrix_size/2; idx=idx+2 ) {
450 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
451 int current_idx_pair = current_idx | (1<<
target_qbit);
453 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
455 float* element = (
float*)input.
get_data() + 2 * current_idx;
458 __m256 data_both = _mm256_loadu_ps(element);
459 __m256 data0 = _mm256_set_m128(_mm256_castps256_ps128(data_both), _mm256_castps256_ps128(data_both));
460 __m256 data1 = _mm256_set_m128(_mm256_extractf128_ps(data_both, 1), _mm256_extractf128_ps(data_both, 1));
462 __m256 data_u2 = _mm256_mul_ps(data0, mv00);
463 __m256 data_u3 = _mm256_mul_ps(data1, mv10);
464 __m256 data_u4 = _mm256_mul_ps(data0, mv01);
465 __m256 data_u5 = _mm256_mul_ps(data1, mv11);
467 __m256 data_u6 = _mm256_hadd_ps(data_u2, data_u4);
468 __m256 data_u7 = _mm256_hadd_ps(data_u3, data_u5);
470 __m256 data_d2 = _mm256_mul_ps(data0, mv20);
471 __m256 data_d3 = _mm256_mul_ps(data1, mv30);
472 __m256 data_d4 = _mm256_mul_ps(data0, mv21);
473 __m256 data_d5 = _mm256_mul_ps(data1, mv31);
475 __m256 data_d6 = _mm256_hadd_ps(data_d2, data_d4);
476 __m256 data_d7 = _mm256_hadd_ps(data_d3, data_d5);
478 __m256 data_r0 = _mm256_add_ps(data_u6, data_u7);
479 __m256 data_r1 = _mm256_add_ps(data_d6, data_d7);
483 __m128 r0 = _mm256_castps256_ps128(data_r0);
484 r0 = _mm_shuffle_ps(r0, r0, _MM_SHUFFLE(3, 1, 2, 0));
485 __m128 r1 = _mm256_castps256_ps128(data_r1);
486 r1 = _mm_shuffle_ps(r1, r1, _MM_SHUFFLE(3, 1, 2, 0));
487 _mm256_storeu_ps(element, _mm256_set_m128(r1, r0));
501 for (
int idx=0; idx<matrix_size/2; idx=idx+4 ) {
503 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
504 int current_idx_pair = current_idx | (1<<
target_qbit);
506 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
508 float* element = (
float*)input.
get_data() + 2 * current_idx;
509 float* element_pair = (
float*)input.
get_data() + 2 * current_idx_pair;
511 __m256 data0 = _mm256_loadu_ps(element);
512 __m256 data1 = _mm256_loadu_ps(element_pair);
514 __m256 data_u2 = _mm256_mul_ps(data0, mv00);
515 __m256 data_u3 = _mm256_mul_ps(data1, mv10);
516 __m256 data_u4 = _mm256_mul_ps(data0, mv01);
517 __m256 data_u5 = _mm256_mul_ps(data1, mv11);
519 __m256 data_u6 = _mm256_hadd_ps(data_u2, data_u4);
520 __m256 data_u7 = _mm256_hadd_ps(data_u3, data_u5);
522 __m256 data_d2 = _mm256_mul_ps(data0, mv20);
523 __m256 data_d3 = _mm256_mul_ps(data1, mv30);
524 __m256 data_d4 = _mm256_mul_ps(data0, mv21);
525 __m256 data_d5 = _mm256_mul_ps(data1, mv31);
527 __m256 data_d6 = _mm256_hadd_ps(data_d2, data_d4);
528 __m256 data_d7 = _mm256_hadd_ps(data_d3, data_d5);
530 __m256 data_r0 = _mm256_add_ps(data_u6, data_u7);
531 __m256 data_r1 = _mm256_add_ps(data_d6, data_d7);
535 data_r0 = _mm256_shuffle_ps(data_r0, data_r0, _MM_SHUFFLE(3, 1, 2, 0));
536 data_r1 = _mm256_shuffle_ps(data_r1, data_r1, _MM_SHUFFLE(3, 1, 2, 0));
537 _mm256_storeu_ps(element, data_r0);
538 _mm256_storeu_ps(element_pair, data_r1);
560 unsigned int bitmask_high = ~bitmask_low;
564 if ( control_qbit == 0 ) {
565 #pragma omp parallel for 566 for (
int idx=0; idx<matrix_size/2; idx++ ) {
569 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
572 int current_idx_pair = current_idx | (1<<
target_qbit);
574 if ( current_idx & control_qbit_step_index ) {
583 input[current_idx].real = tmp1.
real + tmp2.
real;
584 input[current_idx].imag = tmp1.
imag + tmp2.
imag;
589 input[current_idx_pair].real = tmp3.
real + tmp4.
real;
590 input[current_idx_pair].imag = tmp3.
imag + tmp4.
imag;
609 else if ( target_qbit == 0 ) {
629 __m256 mv00 = _mm256_set_ps(-u3_1qbit[1].imag, u3_1qbit[1].
real, -u3_1qbit[0].imag, u3_1qbit[0].real,
630 -u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[0].imag, u3_1qbit[0].real);
631 __m256 mv01 = _mm256_set_ps( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag,
632 u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
633 __m256 mv20 = _mm256_set_ps(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real,
634 -u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
635 __m256 mv21 = _mm256_set_ps( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag,
636 u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
638 #pragma omp parallel for 639 for (
int idx=0; idx<matrix_size/2; idx++ ) {
642 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
644 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
647 float *ptr = (
float*)input.
get_data() + 2 * current_idx;
648 __m128 data_low = _mm_loadu_ps(ptr);
649 __m256
data = _mm256_castps128_ps256(data_low);
650 data = _mm256_insertf128_ps(data, data_low, 1);
652 __m256 data_u0 = _mm256_mul_ps(data, mv00);
653 __m256 data_u1 = _mm256_mul_ps(data, mv01);
654 __m256 data_u2 = _mm256_hadd_ps(data_u0, data_u1);
655 data_u2 = _mm256_permutevar8x32_ps(data_u2, _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7));
657 __m256 data_d0 = _mm256_mul_ps(data, mv20);
658 __m256 data_d1 = _mm256_mul_ps(data, mv21);
659 __m256 data_d2 = _mm256_hadd_ps(data_d0, data_d1);
660 data_d2 = _mm256_permutevar8x32_ps(data_d2, _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7));
662 __m256 data_r = _mm256_hadd_ps(data_u2, data_d2);
664 data_r = _mm256_permutevar8x32_ps(data_r, _mm256_setr_epi32(0, 4, 2, 6, 1, 5, 3, 7));
665 _mm_storeu_ps(ptr, _mm256_castps256_ps128(data_r));
702 __m256 mv00 = _mm256_set_ps(-u3_1qbit[0].imag, u3_1qbit[0].
real, -u3_1qbit[0].imag, u3_1qbit[0].real,
703 -u3_1qbit[0].imag, u3_1qbit[0].real, -u3_1qbit[0].imag, u3_1qbit[0].real);
704 __m256 mv01 = _mm256_set_ps( u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag,
705 u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
706 __m256 mv10 = _mm256_set_ps(-u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real,
707 -u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real);
708 __m256 mv11 = _mm256_set_ps( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag,
709 u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag);
710 __m256 mv20 = _mm256_set_ps(-u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real,
711 -u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
712 __m256 mv21 = _mm256_set_ps( u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag,
713 u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
714 __m256 mv30 = _mm256_set_ps(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real,
715 -u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real);
716 __m256 mv31 = _mm256_set_ps( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag,
717 u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag);
719 if ( target_qbit == 1 ) {
722 #pragma omp parallel for 723 for (
int idx=0; idx<matrix_size/2; idx=idx+2 ) {
725 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
726 int current_idx_pair = current_idx | (1<<
target_qbit);
728 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
730 float* element = (
float*)input.
get_data() + 2 * current_idx;
733 __m256 data_both = _mm256_loadu_ps(element);
734 __m256 data0 = _mm256_set_m128(_mm256_castps256_ps128(data_both), _mm256_castps256_ps128(data_both));
735 __m256 data1 = _mm256_set_m128(_mm256_extractf128_ps(data_both, 1), _mm256_extractf128_ps(data_both, 1));
737 __m256 data_u2 = _mm256_mul_ps(data0, mv00);
738 __m256 data_u3 = _mm256_mul_ps(data1, mv10);
739 __m256 data_u4 = _mm256_mul_ps(data0, mv01);
740 __m256 data_u5 = _mm256_mul_ps(data1, mv11);
742 __m256 data_u6 = _mm256_hadd_ps(data_u2, data_u4);
743 __m256 data_u7 = _mm256_hadd_ps(data_u3, data_u5);
745 __m256 data_d2 = _mm256_mul_ps(data0, mv20);
746 __m256 data_d3 = _mm256_mul_ps(data1, mv30);
747 __m256 data_d4 = _mm256_mul_ps(data0, mv21);
748 __m256 data_d5 = _mm256_mul_ps(data1, mv31);
750 __m256 data_d6 = _mm256_hadd_ps(data_d2, data_d4);
751 __m256 data_d7 = _mm256_hadd_ps(data_d3, data_d5);
753 __m256 data_r0 = _mm256_add_ps(data_u6, data_u7);
754 __m256 data_r1 = _mm256_add_ps(data_d6, data_d7);
758 __m128 r0 = _mm256_castps256_ps128(data_r0);
759 r0 = _mm_shuffle_ps(r0, r0, _MM_SHUFFLE(3, 1, 2, 0));
760 __m128 r1 = _mm256_castps256_ps128(data_r1);
761 r1 = _mm_shuffle_ps(r1, r1, _MM_SHUFFLE(3, 1, 2, 0));
762 _mm256_storeu_ps(element, _mm256_set_m128(r1, r0));
776 #pragma omp parallel for 777 for (
int idx=0; idx<matrix_size/2; idx=idx+4 ) {
779 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
780 int current_idx_pair = current_idx | (1<<
target_qbit);
782 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
784 float* element = (
float*)input.
get_data() + 2 * current_idx;
785 float* element_pair = (
float*)input.
get_data() + 2 * current_idx_pair;
787 __m256 data0 = _mm256_loadu_ps(element);
788 __m256 data1 = _mm256_loadu_ps(element_pair);
790 __m256 data_u2 = _mm256_mul_ps(data0, mv00);
791 __m256 data_u3 = _mm256_mul_ps(data1, mv10);
792 __m256 data_u4 = _mm256_mul_ps(data0, mv01);
793 __m256 data_u5 = _mm256_mul_ps(data1, mv11);
795 __m256 data_u6 = _mm256_hadd_ps(data_u2, data_u4);
796 __m256 data_u7 = _mm256_hadd_ps(data_u3, data_u5);
798 __m256 data_d2 = _mm256_mul_ps(data0, mv20);
799 __m256 data_d3 = _mm256_mul_ps(data1, mv30);
800 __m256 data_d4 = _mm256_mul_ps(data0, mv21);
801 __m256 data_d5 = _mm256_mul_ps(data1, mv31);
803 __m256 data_d6 = _mm256_hadd_ps(data_d2, data_d4);
804 __m256 data_d7 = _mm256_hadd_ps(data_d3, data_d5);
806 __m256 data_r0 = _mm256_add_ps(data_u6, data_u7);
807 __m256 data_r1 = _mm256_add_ps(data_d6, data_d7);
811 data_r0 = _mm256_shuffle_ps(data_r0, data_r0, _MM_SHUFFLE(3, 1, 2, 0));
812 data_r1 = _mm256_shuffle_ps(data_r1, data_r1, _MM_SHUFFLE(3, 1, 2, 0));
813 _mm256_storeu_ps(element, data_r0);
814 _mm256_storeu_ps(element_pair, data_r1);
839 unsigned int bitmask_high = ~bitmask_low;
843 tbb::affinity_partitioner aff_p;
845 if ( control_qbit == 0 ) {
846 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
848 for (
int idx=r.begin(); idx<r.end(); idx++) {
852 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
855 int current_idx_pair = current_idx | (1<<
target_qbit);
857 if ( current_idx & control_qbit_step_index ) {
866 input[current_idx].real = tmp1.
real + tmp2.
real;
867 input[current_idx].imag = tmp1.
imag + tmp2.
imag;
872 input[current_idx_pair].real = tmp3.
real + tmp4.
real;
873 input[current_idx_pair].imag = tmp3.
imag + tmp4.
imag;
895 else if ( target_qbit == 0 ) {
915 __m256 mv00 = _mm256_set_ps(-u3_1qbit[1].imag, u3_1qbit[1].
real, -u3_1qbit[0].imag, u3_1qbit[0].real,
916 -u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[0].imag, u3_1qbit[0].real);
917 __m256 mv01 = _mm256_set_ps( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag,
918 u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
919 __m256 mv20 = _mm256_set_ps(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real,
920 -u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
921 __m256 mv21 = _mm256_set_ps( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag,
922 u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
924 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
926 for (
int idx=r.begin(); idx<r.end(); idx++) {
929 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
931 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
934 float *ptr = (
float*)input.
get_data() + 2 * current_idx;
935 __m128 data_low = _mm_loadu_ps(ptr);
936 __m256
data = _mm256_castps128_ps256(data_low);
937 data = _mm256_insertf128_ps(data, data_low, 1);
939 __m256 data_u0 = _mm256_mul_ps(data, mv00);
940 __m256 data_u1 = _mm256_mul_ps(data, mv01);
941 __m256 data_u2 = _mm256_hadd_ps(data_u0, data_u1);
942 data_u2 = _mm256_permutevar8x32_ps(data_u2, _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7));
944 __m256 data_d0 = _mm256_mul_ps(data, mv20);
945 __m256 data_d1 = _mm256_mul_ps(data, mv21);
946 __m256 data_d2 = _mm256_hadd_ps(data_d0, data_d1);
947 data_d2 = _mm256_permutevar8x32_ps(data_d2, _mm256_setr_epi32(0, 1, 4, 5, 2, 3, 6, 7));
949 __m256 data_r = _mm256_hadd_ps(data_u2, data_d2);
951 data_r = _mm256_permutevar8x32_ps(data_r, _mm256_setr_epi32(0, 4, 2, 6, 1, 5, 3, 7));
952 _mm_storeu_ps(ptr, _mm256_castps256_ps128(data_r));
988 __m256 mv00 = _mm256_set_ps(-u3_1qbit[0].imag, u3_1qbit[0].
real, -u3_1qbit[0].imag, u3_1qbit[0].real,
989 -u3_1qbit[0].imag, u3_1qbit[0].real, -u3_1qbit[0].imag, u3_1qbit[0].real);
990 __m256 mv01 = _mm256_set_ps( u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag,
991 u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
992 __m256 mv10 = _mm256_set_ps(-u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real,
993 -u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real);
994 __m256 mv11 = _mm256_set_ps( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag,
995 u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag);
996 __m256 mv20 = _mm256_set_ps(-u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real,
997 -u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
998 __m256 mv21 = _mm256_set_ps( u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag,
999 u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
1000 __m256 mv30 = _mm256_set_ps(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real,
1001 -u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real);
1002 __m256 mv31 = _mm256_set_ps( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag,
1003 u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag);
1006 if ( target_qbit == 1 ) {
1009 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
1011 for (
int idx=r.begin(); idx<r.end(); idx=idx+2) {
1013 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1014 int current_idx_pair = current_idx | (1<<
target_qbit);
1016 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
1018 float* element = (
float*)input.
get_data() + 2 * current_idx;
1021 __m256 data_both = _mm256_loadu_ps(element);
1022 __m256 data0 = _mm256_set_m128(_mm256_castps256_ps128(data_both), _mm256_castps256_ps128(data_both));
1023 __m256 data1 = _mm256_set_m128(_mm256_extractf128_ps(data_both, 1), _mm256_extractf128_ps(data_both, 1));
1025 __m256 data_u2 = _mm256_mul_ps(data0, mv00);
1026 __m256 data_u3 = _mm256_mul_ps(data1, mv10);
1027 __m256 data_u4 = _mm256_mul_ps(data0, mv01);
1028 __m256 data_u5 = _mm256_mul_ps(data1, mv11);
1030 __m256 data_u6 = _mm256_hadd_ps(data_u2, data_u4);
1031 __m256 data_u7 = _mm256_hadd_ps(data_u3, data_u5);
1033 __m256 data_d2 = _mm256_mul_ps(data0, mv20);
1034 __m256 data_d3 = _mm256_mul_ps(data1, mv30);
1035 __m256 data_d4 = _mm256_mul_ps(data0, mv21);
1036 __m256 data_d5 = _mm256_mul_ps(data1, mv31);
1038 __m256 data_d6 = _mm256_hadd_ps(data_d2, data_d4);
1039 __m256 data_d7 = _mm256_hadd_ps(data_d3, data_d5);
1041 __m256 data_r0 = _mm256_add_ps(data_u6, data_u7);
1042 __m256 data_r1 = _mm256_add_ps(data_d6, data_d7);
1046 __m128 r0 = _mm256_castps256_ps128(data_r0);
1047 r0 = _mm_shuffle_ps(r0, r0, _MM_SHUFFLE(3, 1, 2, 0));
1048 __m128 r1 = _mm256_castps256_ps128(data_r1);
1049 r1 = _mm_shuffle_ps(r1, r1, _MM_SHUFFLE(3, 1, 2, 0));
1050 _mm256_storeu_ps(element, _mm256_set_m128(r1, r0));
1065 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
1067 for (
int idx=r.begin(); idx<r.end(); idx=idx+4) {
1069 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1070 int current_idx_pair = current_idx | (1<<
target_qbit);
1072 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
1074 float* element = (
float*)input.
get_data() + 2 * current_idx;
1075 float* element_pair = (
float*)input.
get_data() + 2 * current_idx_pair;
1077 __m256 data0 = _mm256_loadu_ps(element);
1078 __m256 data1 = _mm256_loadu_ps(element_pair);
1080 __m256 data_u2 = _mm256_mul_ps(data0, mv00);
1081 __m256 data_u3 = _mm256_mul_ps(data1, mv10);
1082 __m256 data_u4 = _mm256_mul_ps(data0, mv01);
1083 __m256 data_u5 = _mm256_mul_ps(data1, mv11);
1085 __m256 data_u6 = _mm256_hadd_ps(data_u2, data_u4);
1086 __m256 data_u7 = _mm256_hadd_ps(data_u3, data_u5);
1088 __m256 data_d2 = _mm256_mul_ps(data0, mv20);
1089 __m256 data_d3 = _mm256_mul_ps(data1, mv30);
1090 __m256 data_d4 = _mm256_mul_ps(data0, mv21);
1091 __m256 data_d5 = _mm256_mul_ps(data1, mv31);
1093 __m256 data_d6 = _mm256_hadd_ps(data_d2, data_d4);
1094 __m256 data_d7 = _mm256_hadd_ps(data_d3, data_d5);
1096 __m256 data_r0 = _mm256_add_ps(data_u6, data_u7);
1097 __m256 data_r1 = _mm256_add_ps(data_d6, data_d7);
1101 data_r0 = _mm256_shuffle_ps(data_r0, data_r0, _MM_SHUFFLE(3, 1, 2, 0));
1102 data_r1 = _mm256_shuffle_ps(data_r1, data_r1, _MM_SHUFFLE(3, 1, 2, 0));
1103 _mm256_storeu_ps(element, data_r0);
1104 _mm256_storeu_ps(element_pair, data_r1);
1233 unsigned int bitmask_low = (1 <<
target_qbit) - 1;
1234 unsigned int bitmask_high = ~bitmask_low;
1238 if ( control_qbit == 0 ) {
1239 #pragma omp parallel for 1240 for (
int idx=0; idx<matrix_size/2; idx++ ) {
1243 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1246 int current_idx_pair = current_idx | (1<<
target_qbit);
1248 if ( current_idx & control_qbit_step_index ) {
1257 input[current_idx].real = tmp1.
real + tmp2.
real;
1258 input[current_idx].imag = tmp1.
imag + tmp2.
imag;
1263 input[current_idx_pair].real = tmp3.
real + tmp4.
real;
1264 input[current_idx_pair].imag = tmp3.
imag + tmp4.
imag;
1283 else if ( target_qbit == 0 ) {
1303 __m256d mv00 = _mm256_set_pd(-u3_1qbit[1].imag, u3_1qbit[1].
real, -u3_1qbit[0].imag, u3_1qbit[0].real);
1304 __m256d mv01 = _mm256_set_pd( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
1305 __m256d mv20 = _mm256_set_pd(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
1306 __m256d mv21 = _mm256_set_pd( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
1308 #pragma omp parallel for 1309 for (
int idx=0; idx<matrix_size/2; idx++ ) {
1312 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1314 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
1317 double *ptr = (
double*)input.
get_data() + 2 * current_idx;
1318 __m256d
data = _mm256_loadu_pd(ptr);
1320 __m256d data_u0 = _mm256_mul_pd(data, mv00);
1321 __m256d data_u1 = _mm256_mul_pd(data, mv01);
1322 __m256d data_u2 = _mm256_hadd_pd(data_u0, data_u1);
1323 data_u2 = _mm256_permute4x64_pd(data_u2, 216);
1325 __m256d data_d0 = _mm256_mul_pd(data, mv20);
1326 __m256d data_d1 = _mm256_mul_pd(data, mv21);
1327 __m256d data_d2 = _mm256_hadd_pd(data_d0, data_d1);
1328 data_d2 = _mm256_permute4x64_pd(data_d2, 216);
1330 __m256d data_r = _mm256_hadd_pd(data_u2, data_d2);
1332 data_r = _mm256_permute4x64_pd(data_r, 216);
1333 _mm256_storeu_pd(ptr, data_r);
1370 __m256d mv00 = _mm256_set_pd(-u3_1qbit[0].imag, u3_1qbit[0].
real, -u3_1qbit[0].imag, u3_1qbit[0].real);
1371 __m256d mv01 = _mm256_set_pd( u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
1372 __m256d mv10 = _mm256_set_pd(-u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real);
1373 __m256d mv11 = _mm256_set_pd( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag);
1374 __m256d mv20 = _mm256_set_pd(-u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
1375 __m256d mv21 = _mm256_set_pd( u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
1376 __m256d mv30 = _mm256_set_pd(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real);
1377 __m256d mv31 = _mm256_set_pd( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag);
1379 #pragma omp parallel for 1380 for (
int idx=0; idx<matrix_size/2; idx=idx+2 ) {
1383 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1386 int current_idx_pair = current_idx | (1<<
target_qbit);
1388 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
1391 double* element = (
double*)input.
get_data() + 2 * current_idx;
1392 double* element_pair = (
double*)input.
get_data() + 2 * current_idx_pair;
1395 __m256d data0 = _mm256_loadu_pd(element);
1396 __m256d data1 = _mm256_loadu_pd(element_pair);
1398 __m256d data_u2 = _mm256_mul_pd(data0, mv00);
1399 __m256d data_u3 = _mm256_mul_pd(data1, mv10);
1400 __m256d data_u4 = _mm256_mul_pd(data0, mv01);
1401 __m256d data_u5 = _mm256_mul_pd(data1, mv11);
1403 __m256d data_u6 = _mm256_hadd_pd(data_u2, data_u4);
1404 __m256d data_u7 = _mm256_hadd_pd(data_u3, data_u5);
1406 __m256d data_d2 = _mm256_mul_pd(data0, mv20);
1407 __m256d data_d3 = _mm256_mul_pd(data1, mv30);
1408 __m256d data_d4 = _mm256_mul_pd(data0, mv21);
1409 __m256d data_d5 = _mm256_mul_pd(data1, mv31);
1411 __m256d data_d6 = _mm256_hadd_pd(data_d2, data_d4);
1412 __m256d data_d7 = _mm256_hadd_pd(data_d3, data_d5);
1414 __m256d data_r0 = _mm256_add_pd(data_u6, data_u7);
1415 __m256d data_r1 = _mm256_add_pd(data_d6, data_d7);
1417 _mm256_storeu_pd(element, data_r0);
1418 _mm256_storeu_pd(element_pair, data_r1);
1462 int grain_size = 64;
1464 unsigned int bitmask_low = (1 <<
target_qbit) - 1;
1465 unsigned int bitmask_high = ~bitmask_low;
1469 tbb::affinity_partitioner aff_p;
1471 if ( control_qbit == 0 ) {
1472 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
1474 for (
int idx=r.begin(); idx<r.end(); idx++) {
1478 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1481 int current_idx_pair = current_idx | (1<<
target_qbit);
1483 if ( current_idx & control_qbit_step_index ) {
1492 input[current_idx].real = tmp1.
real + tmp2.
real;
1493 input[current_idx].imag = tmp1.
imag + tmp2.
imag;
1498 input[current_idx_pair].real = tmp3.
real + tmp4.
real;
1499 input[current_idx_pair].imag = tmp3.
imag + tmp4.
imag;
1521 else if ( target_qbit == 0 ) {
1541 __m256d mv00 = _mm256_set_pd(-u3_1qbit[1].imag, u3_1qbit[1].
real, -u3_1qbit[0].imag, u3_1qbit[0].real);
1542 __m256d mv01 = _mm256_set_pd( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
1543 __m256d mv20 = _mm256_set_pd(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
1544 __m256d mv21 = _mm256_set_pd( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
1546 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
1548 for (
int idx=r.begin(); idx<r.end(); idx++) {
1551 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1553 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
1556 double *ptr = (
double*)input.
get_data() + 2 * current_idx;
1557 __m256d
data = _mm256_loadu_pd(ptr);
1559 __m256d data_u0 = _mm256_mul_pd(data, mv00);
1560 __m256d data_u1 = _mm256_mul_pd(data, mv01);
1561 __m256d data_u2 = _mm256_hadd_pd(data_u0, data_u1);
1562 data_u2 = _mm256_permute4x64_pd(data_u2, 216);
1564 __m256d data_d0 = _mm256_mul_pd(data, mv20);
1565 __m256d data_d1 = _mm256_mul_pd(data, mv21);
1566 __m256d data_d2 = _mm256_hadd_pd(data_d0, data_d1);
1567 data_d2 = _mm256_permute4x64_pd(data_d2, 216);
1569 __m256d data_r = _mm256_hadd_pd(data_u2, data_d2);
1571 data_r = _mm256_permute4x64_pd(data_r, 216);
1572 _mm256_storeu_pd(ptr, data_r);
1608 __m256d mv00 = _mm256_set_pd(-u3_1qbit[0].imag, u3_1qbit[0].
real, -u3_1qbit[0].imag, u3_1qbit[0].real);
1609 __m256d mv01 = _mm256_set_pd( u3_1qbit[0].real, u3_1qbit[0].imag, u3_1qbit[0].real, u3_1qbit[0].imag);
1610 __m256d mv10 = _mm256_set_pd(-u3_1qbit[1].imag, u3_1qbit[1].real, -u3_1qbit[1].imag, u3_1qbit[1].real);
1611 __m256d mv11 = _mm256_set_pd( u3_1qbit[1].real, u3_1qbit[1].imag, u3_1qbit[1].real, u3_1qbit[1].imag);
1612 __m256d mv20 = _mm256_set_pd(-u3_1qbit[2].imag, u3_1qbit[2].real, -u3_1qbit[2].imag, u3_1qbit[2].real);
1613 __m256d mv21 = _mm256_set_pd( u3_1qbit[2].real, u3_1qbit[2].imag, u3_1qbit[2].real, u3_1qbit[2].imag);
1614 __m256d mv30 = _mm256_set_pd(-u3_1qbit[3].imag, u3_1qbit[3].real, -u3_1qbit[3].imag, u3_1qbit[3].real);
1615 __m256d mv31 = _mm256_set_pd( u3_1qbit[3].real, u3_1qbit[3].imag, u3_1qbit[3].real, u3_1qbit[3].imag);
1618 tbb::parallel_for( tbb::blocked_range<int>(0,matrix_size/2,grain_size), [&](tbb::blocked_range<int> r) {
1620 for (
int idx=r.begin(); idx<r.end(); idx=idx+2) {
1622 int current_idx = ((idx & bitmask_high) << 1) | (idx & bitmask_low);
1625 int current_idx_pair = current_idx | (1<<
target_qbit);
1627 if (control_qbit < 0 || (current_idx & control_qbit_step_index) ) {
1630 double* element = (
double*)input.
get_data() + 2 * current_idx;
1631 double* element_pair = (
double*)input.
get_data() + 2 * current_idx_pair;
1634 __m256d data0 = _mm256_loadu_pd(element);
1635 __m256d data1 = _mm256_loadu_pd(element_pair);
1637 __m256d data_u2 = _mm256_mul_pd(data0, mv00);
1638 __m256d data_u3 = _mm256_mul_pd(data1, mv10);
1639 __m256d data_u4 = _mm256_mul_pd(data0, mv01);
1640 __m256d data_u5 = _mm256_mul_pd(data1, mv11);
1642 __m256d data_u6 = _mm256_hadd_pd(data_u2, data_u4);
1643 __m256d data_u7 = _mm256_hadd_pd(data_u3, data_u5);
1645 __m256d data_d2 = _mm256_mul_pd(data0, mv20);
1646 __m256d data_d3 = _mm256_mul_pd(data1, mv30);
1647 __m256d data_d4 = _mm256_mul_pd(data0, mv21);
1648 __m256d data_d5 = _mm256_mul_pd(data1, mv31);
1650 __m256d data_d6 = _mm256_hadd_pd(data_d2, data_d4);
1651 __m256d data_d7 = _mm256_hadd_pd(data_d3, data_d5);
1653 __m256d data_r0 = _mm256_add_pd(data_u6, data_u7);
1654 __m256d data_r1 = _mm256_add_pd(data_d6, data_d7);
1656 _mm256_storeu_pd(element, data_r0);
1657 _mm256_storeu_pd(element_pair, data_r1);
Structure type representing single-precision complex numbers.
data
load the unitary from file
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
scalar * get_data() const
Call to get the pointer to the stored data.
int cols
The number of columns.
Structure type representing complex numbers in the SQUANDER package.
Double-precision complex matrix (float64).
Single-precision complex matrix (float32).
double real
the real part of a complex number
double imag
the imaginary part of a complex number