27 #include <type_traits> 30 template<
typename MatrixT>
31 using StateVecComplexT =
typename std::remove_reference<decltype(std::declval<MatrixT&>()[0])>::type;
33 template<
typename MatrixT>
53 for (
int current_idx_pair=current_idx + index_step_target; current_idx_pair<
matrix_size; current_idx_pair=current_idx_pair+(index_step_target << 1) ) {
55 for (
int idx = 0; idx < index_step_target; idx++) {
58 int current_idx_loc = current_idx + idx;
59 int current_idx_pair_loc = current_idx_pair + idx;
61 int row_offset = current_idx_loc * input.stride;
62 int row_offset_pair = current_idx_pair_loc * input.stride;
64 if (control_qbit < 0 || ((current_idx_loc >> control_qbit) & 1)) {
66 ComplexT element = input[row_offset];
67 ComplexT element_pair = input[row_offset_pair];
69 ComplexT tmp1 =
mult(u3_1qbit[0], element);
70 ComplexT tmp2 =
mult(u3_1qbit[1], element_pair);
72 input[row_offset].real = tmp1.real + tmp2.real;
73 input[row_offset].imag = tmp1.imag + tmp2.imag;
75 tmp1 =
mult(u3_1qbit[2], element);
76 tmp2 =
mult(u3_1qbit[3], element_pair);
78 input[row_offset_pair].real = tmp1.real + tmp2.real;
79 input[row_offset_pair].imag = tmp1.imag + tmp2.imag;
86 memset(input.get_data() + row_offset, 0, input.cols *
sizeof(ComplexT));
87 memset(input.get_data() + row_offset_pair, 0, input.cols *
sizeof(ComplexT));
102 current_idx = current_idx + (index_step_target << 1);
133 template<
typename MatrixT>
142 int parallel_outer_cycles = matrix_size/(index_step_target << 1);
143 int outer_grain_size;
144 if ( index_step_target <= 2 ) {
145 outer_grain_size = 64;
147 else if ( index_step_target <= 4 ) {
148 outer_grain_size = 32;
150 else if ( index_step_target <= 8 ) {
151 outer_grain_size = 16;
153 else if ( index_step_target <= 16 ) {
154 outer_grain_size = 8;
157 outer_grain_size = 2;
160 int inner_grain_size = 64;
162 tbb::parallel_for( tbb::blocked_range<int>(0, parallel_outer_cycles, outer_grain_size), [&](tbb::blocked_range<int> r) {
164 int current_idx = r.begin()*(index_step_target << 1);
165 int current_idx_pair = index_step_target + r.begin()*(index_step_target << 1);
167 for (
int rdx=r.begin(); rdx<r.end(); rdx++) {
170 tbb::parallel_for( tbb::blocked_range<int>(0,index_step_target,inner_grain_size), [&](tbb::blocked_range<int> r) {
171 for (
int idx=r.begin(); idx<r.end(); ++idx) {
175 int current_idx_loc = current_idx + idx;
176 int current_idx_pair_loc = current_idx_pair + idx;
178 int row_offset = current_idx_loc * input.stride;
179 int row_offset_pair = current_idx_pair_loc * input.stride;
181 if (control_qbit < 0 || ((current_idx_loc >> control_qbit) & 1)) {
183 ComplexT element = input[row_offset];
184 ComplexT element_pair = input[row_offset_pair];
186 ComplexT tmp1 =
mult(u3_1qbit[0], element);
187 ComplexT tmp2 =
mult(u3_1qbit[1], element_pair);
189 input[row_offset].real = tmp1.real + tmp2.real;
190 input[row_offset].imag = tmp1.imag + tmp2.imag;
192 tmp1 =
mult(u3_1qbit[2], element);
193 tmp2 =
mult(u3_1qbit[3], element_pair);
195 input[row_offset_pair].real = tmp1.real + tmp2.real;
196 input[row_offset_pair].imag = tmp1.imag + tmp2.imag;
203 memset(input.get_data() + row_offset, 0, input.cols *
sizeof(ComplexT));
204 memset(input.get_data() + row_offset_pair, 0, input.cols *
sizeof(ComplexT));
220 current_idx = current_idx + (index_step_target << 1);
221 current_idx_pair = current_idx_pair + (index_step_target << 1);
244 template<
typename MatrixT>
247 int index_step_outer = 1 << outer_qbit;
248 int index_step_inner = 1 << inner_qbit;
251 for (
int current_idx_pair_outer = current_idx + index_step_outer; current_idx_pair_outer < input.rows; current_idx_pair_outer = current_idx_pair_outer + (index_step_outer << 1)) {
253 for (
int current_idx_inner = 0; current_idx_inner < index_step_outer; current_idx_inner = current_idx_inner + (index_step_inner << 1)) {
255 for (
int idx = 0; idx < index_step_inner; idx++) {
257 int current_idx_outer_loc = current_idx + current_idx_inner + idx;
258 int current_idx_inner_loc = current_idx + current_idx_inner + idx + index_step_inner;
259 int current_idx_outer_pair_loc = current_idx_pair_outer + idx + current_idx_inner;
260 int current_idx_inner_pair_loc = current_idx_pair_outer + idx + current_idx_inner + index_step_inner;
261 int indexes[4] = {current_idx_outer_loc, current_idx_inner_loc, current_idx_outer_pair_loc, current_idx_inner_pair_loc};
272 for (
int mult_idx = 0; mult_idx < 4; mult_idx++) {
274 tmp1 =
mult(two_qbit_unitary[mult_idx * 4], element_outer);
275 tmp2 =
mult(two_qbit_unitary[mult_idx * 4 + 1], element_inner);
276 tmp3 =
mult(two_qbit_unitary[mult_idx * 4 + 2], element_outer_pair);
277 tmp4 =
mult(two_qbit_unitary[mult_idx * 4 + 3], element_inner_pair);
278 input[indexes[mult_idx]].real = tmp1.real + tmp2.real + tmp3.real + tmp4.real;
279 input[indexes[mult_idx]].imag = tmp1.imag + tmp2.imag + tmp3.imag + tmp4.imag;
283 current_idx = current_idx + (index_step_outer << 1);
289 template<
typename MatrixT>
292 int index_step_inner = 1 << involved_qbits[0];
293 int index_step_middle = 1 << involved_qbits[1];
294 int index_step_outer = 1 << involved_qbits[2];
297 for (
int current_idx_pair_outer = current_idx + index_step_outer; current_idx_pair_outer < input.rows; current_idx_pair_outer = current_idx_pair_outer + (index_step_outer << 1)) {
299 for (
int current_idx_middle = 0; current_idx_middle < index_step_outer; current_idx_middle = current_idx_middle + (index_step_middle << 1)) {
301 for (
int current_idx_inner = 0; current_idx_inner < index_step_middle; current_idx_inner = current_idx_inner + (index_step_inner << 1)) {
303 for (
int idx = 0; idx < index_step_inner; idx++) {
305 int current_idx_loc = current_idx + current_idx_middle + current_idx_inner + idx;
306 int current_idx_pair_loc = current_idx_pair_outer + idx + current_idx_inner + current_idx_middle;
308 int current_idx_outer_loc = current_idx_loc;
309 int current_idx_inner_loc = current_idx_loc + index_step_inner;
311 int current_idx_middle_loc = current_idx_loc + index_step_middle;
312 int current_idx_middle_inner_loc = current_idx_loc + index_step_middle + index_step_inner;
314 int current_idx_outer_pair_loc = current_idx_pair_loc;
315 int current_idx_inner_pair_loc = current_idx_pair_loc + index_step_inner;
317 int current_idx_middle_pair_loc = current_idx_pair_loc + index_step_middle;
318 int current_idx_middle_inner_pair_loc = current_idx_pair_loc + index_step_middle + index_step_inner;
320 int indexes[8] = {current_idx_outer_loc, current_idx_inner_loc, current_idx_middle_loc, current_idx_middle_inner_loc, current_idx_outer_pair_loc, current_idx_inner_pair_loc, current_idx_middle_pair_loc, current_idx_middle_inner_pair_loc};
341 for (
int mult_idx = 0; mult_idx < 8; mult_idx++) {
342 tmp1 =
mult(unitary[mult_idx * 8], element_outer);
343 tmp2 =
mult(unitary[mult_idx * 8 + 1], element_inner);
344 tmp3 =
mult(unitary[mult_idx * 8 + 2], element_middle);
345 tmp4 =
mult(unitary[mult_idx * 8 + 3], element_middle_inner);
346 tmp5 =
mult(unitary[mult_idx * 8 + 4], element_outer_pair);
347 tmp6 =
mult(unitary[mult_idx * 8 + 5], element_inner_pair);
348 tmp7 =
mult(unitary[mult_idx * 8 + 6], element_middle_pair);
349 tmp8 =
mult(unitary[mult_idx * 8 + 7], element_middle_inner_pair);
350 input[indexes[mult_idx]].real = tmp1.real + tmp2.real + tmp3.real + tmp4.real + tmp5.real + tmp6.real + tmp7.real + tmp8.real;
351 input[indexes[mult_idx]].imag = tmp1.imag + tmp2.imag + tmp3.imag + tmp4.imag + tmp5.imag + tmp6.imag + tmp7.imag + tmp8.imag;
356 current_idx = current_idx + (index_step_outer << 1);
362 template<
typename MatrixT>
365 int index_step_q0 = 1 << involved_qbits[0];
366 int index_step_q1 = 1 << involved_qbits[1];
367 int index_step_q2 = 1 << involved_qbits[2];
368 int index_step_q3 = 1 << involved_qbits[3];
372 for (
int current_idx_pair_q3 = current_idx + index_step_q3; current_idx_pair_q3 < input.rows; current_idx_pair_q3 += (index_step_q3 << 1)) {
373 for (
int current_idx_q2 = 0; current_idx_q2 < index_step_q3; current_idx_q2 += (index_step_q2 << 1)) {
374 for (
int current_idx_q1 = 0; current_idx_q1 < index_step_q2; current_idx_q1 += (index_step_q1 << 1)) {
375 for (
int current_idx_q0 = 0; current_idx_q0 < index_step_q1; current_idx_q0 += (index_step_q0 << 1)) {
376 for (
int idx = 0; idx < index_step_q0; idx++) {
378 int current_idx_loc = current_idx + current_idx_q2 + current_idx_q1 + current_idx_q0 + idx;
379 int current_idx_pair_loc = current_idx_pair_q3 + idx + current_idx_q1 + current_idx_q2 + current_idx_q0;
381 int current_idx_q0_0_loc = current_idx_loc;
382 int current_idx_q0_1_loc = current_idx_loc + index_step_q0;
383 int current_idx_q1_0_loc = current_idx_loc + index_step_q1;
384 int current_idx_q1_1_loc = current_idx_loc + index_step_q1 + index_step_q0;
385 int current_idx_q2_0_loc = current_idx_loc + index_step_q2;
386 int current_idx_q2_1_loc = current_idx_loc + index_step_q2 + index_step_q0;
387 int current_idx_q2_q1_0_loc = current_idx_loc + index_step_q2 + index_step_q1;
388 int current_idx_q2_q1_1_loc = current_idx_loc + index_step_q2 + index_step_q1 + index_step_q0;
390 int current_idx_q3_q0_0_pair_loc = current_idx_pair_loc;
391 int current_idx_q3_q0_1_pair_loc = current_idx_pair_loc + index_step_q0;
392 int current_idx_q3_q1_0_pair_loc = current_idx_pair_loc + index_step_q1;
393 int current_idx_q3_q1_1_pair_loc = current_idx_pair_loc + index_step_q1 + index_step_q0;
394 int current_idx_q3_q2_0_pair_loc = current_idx_pair_loc + index_step_q2;
395 int current_idx_q3_q2_1_pair_loc = current_idx_pair_loc + index_step_q2 + index_step_q0;
396 int current_idx_q3_q2_q1_0_pair_loc = current_idx_pair_loc + index_step_q2 + index_step_q1;
397 int current_idx_q3_q2_q1_1_pair_loc = current_idx_pair_loc + index_step_q2 + index_step_q1 + index_step_q0;
400 current_idx_q0_0_loc, current_idx_q0_1_loc, current_idx_q1_0_loc, current_idx_q1_1_loc,
401 current_idx_q2_0_loc, current_idx_q2_1_loc, current_idx_q2_q1_0_loc, current_idx_q2_q1_1_loc,
402 current_idx_q3_q0_0_pair_loc, current_idx_q3_q0_1_pair_loc, current_idx_q3_q1_0_pair_loc, current_idx_q3_q1_1_pair_loc,
403 current_idx_q3_q2_0_pair_loc, current_idx_q3_q2_1_pair_loc, current_idx_q3_q2_q1_0_pair_loc, current_idx_q3_q2_q1_1_pair_loc
423 for (
int mult_idx = 0; mult_idx < 16; mult_idx++) {
441 input[indexes[mult_idx]].real = tmp0.real + tmp1.real + tmp2.real + tmp3.real
442 + tmp4.real + tmp5.real + tmp6.real + tmp7.real
443 + tmp8.real + tmp9.real + tmp10.real + tmp11.real
444 + tmp12.real + tmp13.real + tmp14.real + tmp15.real;
446 input[indexes[mult_idx]].imag = tmp0.imag + tmp1.imag + tmp2.imag + tmp3.imag
447 + tmp4.imag + tmp5.imag + tmp6.imag + tmp7.imag
448 + tmp8.imag + tmp9.imag + tmp10.imag + tmp11.imag
449 + tmp12.imag + tmp13.imag + tmp14.imag + tmp15.imag;
455 current_idx += (index_step_q3 << 1);
461 template<
typename MatrixT>
464 int index_step_q0 = 1 << involved_qbits[0];
465 int index_step_q1 = 1 << involved_qbits[1];
466 int index_step_q2 = 1 << involved_qbits[2];
467 int index_step_q3 = 1 << involved_qbits[3];
468 int index_step_q4 = 1 << involved_qbits[4];
472 for (
int current_idx_pair_q4 = current_idx + index_step_q4; current_idx_pair_q4 < input.rows; current_idx_pair_q4 += (index_step_q4 << 1)) {
473 for (
int current_idx_q3 = 0; current_idx_q3 < index_step_q4; current_idx_q3 += (index_step_q3 << 1)) {
474 for (
int current_idx_q2 = 0; current_idx_q2 < index_step_q3; current_idx_q2 += (index_step_q2 << 1)) {
475 for (
int current_idx_q1 = 0; current_idx_q1 < index_step_q2; current_idx_q1 += (index_step_q1 << 1)) {
476 for (
int current_idx_q0 = 0; current_idx_q0 < index_step_q1; current_idx_q0 += (index_step_q0 << 1)) {
477 for (
int idx = 0; idx < index_step_q0; idx++) {
479 int current_idx_loc = current_idx + current_idx_q3 + current_idx_q2 + current_idx_q1 + current_idx_q0 + idx;
480 int current_idx_pair_q4_loc = current_idx_pair_q4 + idx + current_idx_q1 + current_idx_q2 + current_idx_q3 + current_idx_q0;
482 int current_idx_q0_0_loc = current_idx_loc;
483 int current_idx_q0_1_loc = current_idx_loc + index_step_q0;
484 int current_idx_q1_0_loc = current_idx_loc + index_step_q1;
485 int current_idx_q1_1_loc = current_idx_loc + index_step_q1 + index_step_q0;
486 int current_idx_q2_0_loc = current_idx_loc + index_step_q2;
487 int current_idx_q2_1_loc = current_idx_loc + index_step_q2 + index_step_q0;
488 int current_idx_q2_q1_0_loc = current_idx_loc + index_step_q2 + index_step_q1;
489 int current_idx_q2_q1_1_loc = current_idx_loc + index_step_q2 + index_step_q1 + index_step_q0;
490 int current_idx_q3_0_loc = current_idx_loc + index_step_q3;
491 int current_idx_q3_1_loc = current_idx_loc + index_step_q3 + index_step_q0;
492 int current_idx_q3_q1_0_loc = current_idx_loc + index_step_q3 + index_step_q1;
493 int current_idx_q3_q1_1_loc = current_idx_loc + index_step_q3 + index_step_q1 + index_step_q0;
494 int current_idx_q3_q2_0_loc = current_idx_loc + index_step_q3 + index_step_q2;
495 int current_idx_q3_q2_1_loc = current_idx_loc + index_step_q3 + index_step_q2 + index_step_q0;
496 int current_idx_q3_q2_q1_0_loc = current_idx_loc + index_step_q3 + index_step_q2 + index_step_q1;
497 int current_idx_q3_q2_q1_1_loc = current_idx_loc + index_step_q3 + index_step_q2 + index_step_q1 + index_step_q0;
499 int current_idx_q4_q0_0_pair_loc = current_idx_pair_q4_loc;
500 int current_idx_q4_q0_1_pair_loc = current_idx_pair_q4_loc + index_step_q0;
501 int current_idx_q4_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q1;
502 int current_idx_q4_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q1 + index_step_q0;
503 int current_idx_q4_q2_0_pair_loc = current_idx_pair_q4_loc + index_step_q2;
504 int current_idx_q4_q2_1_pair_loc = current_idx_pair_q4_loc + index_step_q2 + index_step_q0;
505 int current_idx_q4_q2_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q2 + index_step_q1;
506 int current_idx_q4_q2_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q2 + index_step_q1 + index_step_q0;
507 int current_idx_q4_q3_0_pair_loc = current_idx_pair_q4_loc + index_step_q3;
508 int current_idx_q4_q3_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q0;
509 int current_idx_q4_q3_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q1;
510 int current_idx_q4_q3_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q1 + index_step_q0;
511 int current_idx_q4_q3_q2_0_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2;
512 int current_idx_q4_q3_q2_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2 + index_step_q0;
513 int current_idx_q4_q3_q2_q1_0_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2 + index_step_q1;
514 int current_idx_q4_q3_q2_q1_1_pair_loc = current_idx_pair_q4_loc + index_step_q3 + index_step_q2 + index_step_q1 + index_step_q0;
517 current_idx_q0_0_loc, current_idx_q0_1_loc, current_idx_q1_0_loc, current_idx_q1_1_loc,
518 current_idx_q2_0_loc, current_idx_q2_1_loc, current_idx_q2_q1_0_loc, current_idx_q2_q1_1_loc,
519 current_idx_q3_0_loc, current_idx_q3_1_loc, current_idx_q3_q1_0_loc, current_idx_q3_q1_1_loc,
520 current_idx_q3_q2_0_loc, current_idx_q3_q2_1_loc, current_idx_q3_q2_q1_0_loc, current_idx_q3_q2_q1_1_loc,
521 current_idx_q4_q0_0_pair_loc, current_idx_q4_q0_1_pair_loc, current_idx_q4_q1_0_pair_loc, current_idx_q4_q1_1_pair_loc,
522 current_idx_q4_q2_0_pair_loc, current_idx_q4_q2_1_pair_loc, current_idx_q4_q2_q1_0_pair_loc, current_idx_q4_q2_q1_1_pair_loc,
523 current_idx_q4_q3_0_pair_loc, current_idx_q4_q3_1_pair_loc, current_idx_q4_q3_q1_0_pair_loc, current_idx_q4_q3_q1_1_pair_loc,
524 current_idx_q4_q3_q2_0_pair_loc, current_idx_q4_q3_q2_1_pair_loc, current_idx_q4_q3_q2_q1_0_pair_loc, current_idx_q4_q3_q2_q1_1_pair_loc
560 for (
int mult_idx = 0; mult_idx < 32; mult_idx++) {
594 input[indexes[mult_idx]].real = tmp1.real + tmp2.real + tmp3.real + tmp4.real
595 + tmp5.real + tmp6.real + tmp7.real + tmp8.real + tmp9.real + tmp10.real
596 + tmp11.real + tmp12.real + tmp13.real + tmp14.real + tmp15.real + tmp16.real
597 + tmp17.real + tmp18.real + tmp19.real + tmp20.real + tmp21.real + tmp22.real
598 + tmp23.real + tmp24.real + tmp25.real + tmp26.real + tmp27.real + tmp28.real
599 + tmp29.real + tmp30.real + tmp31.real + tmp32.real;
601 input[indexes[mult_idx]].imag = tmp1.imag + tmp2.imag + tmp3.imag + tmp4.imag
602 + tmp5.imag + tmp6.imag + tmp7.imag + tmp8.imag + tmp9.imag + tmp10.imag
603 + tmp11.imag + tmp12.imag + tmp13.imag + tmp14.imag + tmp15.imag + tmp16.imag
604 + tmp17.imag + tmp18.imag + tmp19.imag + tmp20.imag + tmp21.imag + tmp22.imag
605 + tmp23.imag + tmp24.imag + tmp25.imag + tmp26.imag + tmp27.imag + tmp28.imag
606 + tmp29.imag + tmp30.imag + tmp31.imag + tmp32.imag;
613 current_idx += (index_step_q4 << 1);
QGD_Complex16 mult(QGD_Complex16 &a, QGD_Complex16 &b)
Call to calculate the product of two complex scalars.
Double-precision complex matrix (float64).
Single-precision complex matrix (float32).