204 const int stride_in_given,
205 const int stride_out_given)
207 const int mm = transpose_matrix ? n_rows : n_columns,
208 nn = transpose_matrix ? n_columns : n_rows;
209 Assert(n_rows > 0 && n_columns > 0,
211 Assert(n_rows > 0 && n_columns > 0,
213 std::to_string(n_rows) +
", " +
214 std::to_string(n_columns) +
" was passed!"));
217 "This function should only use EvaluatorQuantity::value");
219 Assert(consider_strides || (stride_in_given == 1 && stride_out_given == 1),
221 const int stride_in = consider_strides ? stride_in_given : 1;
222 const int stride_out = consider_strides ? stride_out_given : 1;
224 static_assert(n_components > 0 && n_components < 4,
225 "Invalid number of components");
232 if (transpose_matrix && n_rows == 2 && n_components == 1)
234 const Number2 *matrix_1 = matrix + n_columns;
235 const Number x0 = in[0], x1 = in[stride_in];
236 for (
int col = 0; col < nn; ++col)
238 const Number result = matrix[col] * x0 + matrix_1[col] * x1;
240 out[stride_out * col] += result;
242 out[stride_out * col] = result;
245 else if (transpose_matrix && n_rows == 3 && n_components == 1)
247 const Number2 *matrix_1 = matrix + n_columns;
248 const Number2 *matrix_2 = matrix_1 + n_columns;
249 const Number x0 = in[0], x1 = in[stride_in], x2 = in[2 * stride_in];
250 for (
int col = 0; col < nn; ++col)
252 const Number result =
253 matrix[col] * x0 + matrix_1[col] * x1 + matrix_2[col] * x2;
255 out[stride_out * col] += result;
257 out[stride_out * col] = result;
265 std::array<Number, 129> x;
266 for (
int i = 0; i < mm; ++i)
267 x[i] = in[stride_in * i];
269 for (
int col = 0; col < nn; ++col)
272 if (transpose_matrix ==
true)
274 res0 = matrix[col] * x[0];
275 for (
int i = 1; i < mm; ++i)
276 res0 += matrix[i * n_columns + col] * x[i];
280 res0 = matrix[col * n_columns] * x[0];
281 for (
int i = 1; i < mm; ++i)
282 res0 += matrix[col * n_columns + i] * x[i];
285 out[stride_out * col] += res0;
287 out[stride_out * col] = res0;
292 const Number *in0 = in;
293 const Number *in1 = n_components > 1 ? in + mm :
nullptr;
294 const Number *in2 = n_components > 2 ? in + 2 * mm :
nullptr;
297 Number *out1 = n_components > 1 ? out + nn :
nullptr;
298 Number *out2 = n_components > 2 ? out + 2 * nn :
nullptr;
300 int nn_regular = (nn / 4) * 4;
301 for (
int col = 0; col < nn_regular; col += 4)
304 if (transpose_matrix ==
true)
306 const Number2 *matrix_ptr = matrix + col;
307 const Number a = in0[0];
308 res[0] = matrix_ptr[0] * a;
309 res[1] = matrix_ptr[1] * a;
310 res[2] = matrix_ptr[2] * a;
311 res[3] = matrix_ptr[3] * a;
313 if (n_components > 1)
315 const Number b = in1[0];
316 res[4] = matrix_ptr[0] * b;
317 res[5] = matrix_ptr[1] * b;
318 res[6] = matrix_ptr[2] * b;
319 res[7] = matrix_ptr[3] * b;
322 if (n_components > 2)
324 const Number c = in2[0];
325 res[8] = matrix_ptr[0] * c;
326 res[9] = matrix_ptr[1] * c;
327 res[10] = matrix_ptr[2] * c;
328 res[11] = matrix_ptr[3] * c;
331 matrix_ptr += n_columns;
332 for (
int i = 1; i < mm; ++i, matrix_ptr += n_columns)
334 const Number a = in0[stride_in * i];
335 res[0] += matrix_ptr[0] * a;
336 res[1] += matrix_ptr[1] * a;
337 res[2] += matrix_ptr[2] * a;
338 res[3] += matrix_ptr[3] * a;
340 if (n_components > 1)
342 const Number b = in1[stride_in * i];
343 res[4] += matrix_ptr[0] * b;
344 res[5] += matrix_ptr[1] * b;
345 res[6] += matrix_ptr[2] * b;
346 res[7] += matrix_ptr[3] * b;
348 if (n_components > 2)
350 const Number c = in2[stride_in * i];
351 res[8] += matrix_ptr[0] * c;
352 res[9] += matrix_ptr[1] * c;
353 res[10] += matrix_ptr[2] * c;
354 res[11] += matrix_ptr[3] * c;
360 const Number2 *matrix_0 = matrix + col * n_columns;
361 const Number2 *matrix_1 = matrix + (col + 1) * n_columns;
362 const Number2 *matrix_2 = matrix + (col + 2) * n_columns;
363 const Number2 *matrix_3 = matrix + (col + 3) * n_columns;
365 const Number a = in0[0];
366 res[0] = matrix_0[0] * a;
367 res[1] = matrix_1[0] * a;
368 res[2] = matrix_2[0] * a;
369 res[3] = matrix_3[0] * a;
371 if (n_components > 1)
373 const Number b = in1[0];
374 res[4] = matrix_0[0] * b;
375 res[5] = matrix_1[0] * b;
376 res[6] = matrix_2[0] * b;
377 res[7] = matrix_3[0] * b;
380 if (n_components > 2)
382 const Number c = in2[0];
383 res[8] = matrix_0[0] * c;
384 res[9] = matrix_1[0] * c;
385 res[10] = matrix_2[0] * c;
386 res[11] = matrix_3[0] * c;
389 for (
int i = 1; i < mm; ++i)
391 const Number a = in0[stride_in * i];
392 res[0] += matrix_0[i] * a;
393 res[1] += matrix_1[i] * a;
394 res[2] += matrix_2[i] * a;
395 res[3] += matrix_3[i] * a;
397 if (n_components > 1)
399 const Number b = in1[stride_in * i];
400 res[4] += matrix_0[i] * b;
401 res[5] += matrix_1[i] * b;
402 res[6] += matrix_2[i] * b;
403 res[7] += matrix_3[i] * b;
406 if (n_components > 2)
408 const Number c = in2[stride_in * i];
409 res[8] += matrix_0[i] * c;
410 res[9] += matrix_1[i] * c;
411 res[10] += matrix_2[i] * c;
412 res[11] += matrix_3[i] * c;
419 out0[stride_out] += res[1];
420 out0[2 * stride_out] += res[2];
421 out0[3 * stride_out] += res[3];
422 if (n_components > 1)
425 out1[stride_out] += res[5];
426 out1[2 * stride_out] += res[6];
427 out1[3 * stride_out] += res[7];
429 if (n_components > 2)
432 out2[stride_out] += res[9];
433 out2[2 * stride_out] += res[10];
434 out2[3 * stride_out] += res[11];
440 out0[stride_out] = res[1];
441 out0[2 * stride_out] = res[2];
442 out0[3 * stride_out] = res[3];
443 if (n_components > 1)
446 out1[stride_out] = res[5];
447 out1[2 * stride_out] = res[6];
448 out1[3 * stride_out] = res[7];
450 if (n_components > 2)
453 out2[stride_out] = res[9];
454 out2[2 * stride_out] = res[10];
455 out2[3 * stride_out] = res[11];
458 out0 += 4 * stride_out;
459 if (n_components > 1)
460 out1 += 4 * stride_out;
461 if (n_components > 2)
462 out2 += 4 * stride_out;
464 if (nn - nn_regular == 3)
466 Number res0, res1, res2, res3, res4, res5, res6, res7, res8;
467 if (transpose_matrix ==
true)
469 const Number2 *matrix_ptr = matrix + nn_regular;
470 res0 = matrix_ptr[0] * in0[0];
471 res1 = matrix_ptr[1] * in0[0];
472 res2 = matrix_ptr[2] * in0[0];
473 if (n_components > 1)
475 res3 = matrix_ptr[0] * in1[0];
476 res4 = matrix_ptr[1] * in1[0];
477 res5 = matrix_ptr[2] * in1[0];
479 if (n_components > 2)
481 res6 = matrix_ptr[0] * in2[0];
482 res7 = matrix_ptr[1] * in2[0];
483 res8 = matrix_ptr[2] * in2[0];
485 matrix_ptr += n_columns;
486 for (
int i = 1; i < mm; ++i, matrix_ptr += n_columns)
488 res0 += matrix_ptr[0] * in0[stride_in * i];
489 res1 += matrix_ptr[1] * in0[stride_in * i];
490 res2 += matrix_ptr[2] * in0[stride_in * i];
491 if (n_components > 1)
493 res3 += matrix_ptr[0] * in1[stride_in * i];
494 res4 += matrix_ptr[1] * in1[stride_in * i];
495 res5 += matrix_ptr[2] * in1[stride_in * i];
497 if (n_components > 2)
499 res6 += matrix_ptr[0] * in2[stride_in * i];
500 res7 += matrix_ptr[1] * in2[stride_in * i];
501 res8 += matrix_ptr[2] * in2[stride_in * i];
507 const Number2 *matrix_0 = matrix + nn_regular * n_columns;
508 const Number2 *matrix_1 = matrix + (nn_regular + 1) * n_columns;
509 const Number2 *matrix_2 = matrix + (nn_regular + 2) * n_columns;
511 res0 = matrix_0[0] * in0[0];
512 res1 = matrix_1[0] * in0[0];
513 res2 = matrix_2[0] * in0[0];
514 if (n_components > 1)
516 res3 = matrix_0[0] * in1[0];
517 res4 = matrix_1[0] * in1[0];
518 res5 = matrix_2[0] * in1[0];
520 if (n_components > 2)
522 res6 = matrix_0[0] * in2[0];
523 res7 = matrix_1[0] * in2[0];
524 res8 = matrix_2[0] * in2[0];
526 for (
int i = 1; i < mm; ++i)
528 res0 += matrix_0[i] * in0[stride_in * i];
529 res1 += matrix_1[i] * in0[stride_in * i];
530 res2 += matrix_2[i] * in0[stride_in * i];
531 if (n_components > 1)
533 res3 += matrix_0[i] * in1[stride_in * i];
534 res4 += matrix_1[i] * in1[stride_in * i];
535 res5 += matrix_2[i] * in1[stride_in * i];
537 if (n_components > 2)
539 res6 += matrix_0[i] * in2[stride_in * i];
540 res7 += matrix_1[i] * in2[stride_in * i];
541 res8 += matrix_2[i] * in2[stride_in * i];
548 out0[stride_out] += res1;
549 out0[2 * stride_out] += res2;
550 if (n_components > 1)
553 out1[stride_out] += res4;
554 out1[2 * stride_out] += res5;
556 if (n_components > 2)
559 out2[stride_out] += res7;
560 out2[2 * stride_out] += res8;
566 out0[stride_out] = res1;
567 out0[2 * stride_out] = res2;
568 if (n_components > 1)
571 out1[stride_out] = res4;
572 out1[2 * stride_out] = res5;
574 if (n_components > 2)
577 out2[stride_out] = res7;
578 out2[2 * stride_out] = res8;
582 else if (nn - nn_regular == 2)
584 Number res0, res1, res2, res3, res4, res5;
585 if (transpose_matrix ==
true)
587 const Number2 *matrix_ptr = matrix + nn_regular;
588 res0 = matrix_ptr[0] * in0[0];
589 res1 = matrix_ptr[1] * in0[0];
590 if (n_components > 1)
592 res2 = matrix_ptr[0] * in1[0];
593 res3 = matrix_ptr[1] * in1[0];
595 if (n_components > 2)
597 res4 = matrix_ptr[0] * in2[0];
598 res5 = matrix_ptr[1] * in2[0];
600 matrix_ptr += n_columns;
601 for (
int i = 1; i < mm; ++i, matrix_ptr += n_columns)
603 res0 += matrix_ptr[0] * in0[stride_in * i];
604 res1 += matrix_ptr[1] * in0[stride_in * i];
605 if (n_components > 1)
607 res2 += matrix_ptr[0] * in1[stride_in * i];
608 res3 += matrix_ptr[1] * in1[stride_in * i];
610 if (n_components > 2)
612 res4 += matrix_ptr[0] * in2[stride_in * i];
613 res5 += matrix_ptr[1] * in2[stride_in * i];
619 const Number2 *matrix_0 = matrix + nn_regular * n_columns;
620 const Number2 *matrix_1 = matrix + (nn_regular + 1) * n_columns;
622 res0 = matrix_0[0] * in0[0];
623 res1 = matrix_1[0] * in0[0];
624 if (n_components > 1)
626 res2 = matrix_0[0] * in1[0];
627 res3 = matrix_1[0] * in1[0];
629 if (n_components > 2)
631 res4 = matrix_0[0] * in2[0];
632 res5 = matrix_1[0] * in2[0];
634 for (
int i = 1; i < mm; ++i)
636 res0 += matrix_0[i] * in0[stride_in * i];
637 res1 += matrix_1[i] * in0[stride_in * i];
638 if (n_components > 1)
640 res2 += matrix_0[i] * in1[stride_in * i];
641 res3 += matrix_1[i] * in1[stride_in * i];
643 if (n_components > 2)
645 res4 += matrix_0[i] * in2[stride_in * i];
646 res5 += matrix_1[i] * in2[stride_in * i];
653 out0[stride_out] += res1;
654 if (n_components > 1)
657 out1[stride_out] += res3;
659 if (n_components > 2)
662 out2[stride_out] += res5;
668 out0[stride_out] = res1;
669 if (n_components > 1)
672 out1[stride_out] = res3;
674 if (n_components > 2)
677 out2[stride_out] = res5;
681 else if (nn - nn_regular == 1)
683 Number res0, res1, res2;
684 if (transpose_matrix ==
true)
686 const Number2 *matrix_ptr = matrix + nn_regular;
687 res0 = matrix_ptr[0] * in0[0];
688 if (n_components > 1)
689 res1 = matrix_ptr[0] * in1[0];
690 if (n_components > 2)
691 res2 = matrix_ptr[0] * in2[0];
692 matrix_ptr += n_columns;
693 for (
int i = 1; i < mm; ++i, matrix_ptr += n_columns)
695 res0 += matrix_ptr[0] * in0[stride_in * i];
696 if (n_components > 1)
697 res1 += matrix_ptr[0] * in1[stride_in * i];
698 if (n_components > 2)
699 res2 += matrix_ptr[0] * in2[stride_in * i];
704 const Number2 *matrix_ptr = matrix + nn_regular * n_columns;
705 res0 = matrix_ptr[0] * in0[0];
706 if (n_components > 1)
707 res1 = matrix_ptr[0] * in1[0];
708 if (n_components > 2)
709 res2 = matrix_ptr[0] * in2[0];
710 for (
int i = 1; i < mm; ++i)
712 res0 += matrix_ptr[i] * in0[stride_in * i];
713 if (n_components > 1)
714 res1 += matrix_ptr[i] * in1[stride_in * i];
715 if (n_components > 2)
716 res2 += matrix_ptr[i] * in2[stride_in * i];
722 if (n_components > 1)
724 if (n_components > 2)
730 if (n_components > 1)
732 if (n_components > 2)
765 static_assert(n_rows > 0 || n_columns > 0,
766 "Specialization only for n_rows, n_columns > 0");
767 Assert(n_rows > 0 && n_columns > 0,
769 std::to_string(n_rows) +
", " +
770 std::to_string(n_columns) +
" was passed!"));
772 constexpr int mm = transpose_matrix ? n_rows : n_columns,
773 nn = transpose_matrix ? n_columns : n_rows;
774 constexpr int n_cols = nn / 2;
775 constexpr int mid = mm / 2;
777 std::array<Number, mm> x;
778 for (
int i = 0; i < mm; ++i)
779 x[i] = in[stride_in * i];
802 for (
int col = 0; col < n_cols; ++col)
806 if (transpose_matrix ==
true)
809 val1 = matrix[nn - 1 - col];
813 val0 = matrix[col * n_columns];
814 val1 = matrix[(col + 1) * n_columns - 1];
820 res0 += val1 * x[mm - 1];
821 res1 += val0 * x[mm - 1];
822 for (
int ind = 1; ind < mid; ++ind)
824 if (transpose_matrix ==
true)
826 val0 = matrix[ind * n_columns + col];
827 val1 = matrix[ind * n_columns + nn - 1 - col];
831 val0 = matrix[col * n_columns + ind];
832 val1 = matrix[(col + 1) * n_columns - 1 - ind];
834 res0 += val0 * x[ind];
835 res1 += val1 * x[ind];
836 res0 += val1 * x[mm - 1 - ind];
837 res1 += val0 * x[mm - 1 - ind];
841 res0 = res1 = Number();
842 if (transpose_matrix ==
true)
846 const Number tmp = matrix[mid * n_columns + col] * x[mid];
853 if (mm % 2 == 1 && nn % 2 == 0)
855 const Number tmp = matrix[col * n_columns + mid] * x[mid];
862 out[stride_out * col] += res0;
863 out[stride_out * (nn - 1 - col)] += res1;
867 out[stride_out * col] = res0;
868 out[stride_out * (nn - 1 - col)] = res1;
871 if (transpose_matrix ==
true && nn % 2 == 1 && mm % 2 == 1)
874 out[stride_out * n_cols] += x[mid];
876 out[stride_out * n_cols] = x[mid];
878 else if (transpose_matrix ==
true && nn % 2 == 1)
883 res0 = matrix[n_cols] * (x[0] + x[mm - 1]);
884 for (
int ind = 1; ind < mid; ++ind)
886 const Number2 val0 = matrix[ind * n_columns + n_cols];
887 res0 += val0 * (x[ind] + in[mm - 1 - ind]);
893 out[stride_out * n_cols] += res0;
895 out[stride_out * n_cols] = res0;
897 else if (transpose_matrix ==
false && nn % 2 == 1)
902 res0 = matrix[n_cols * n_columns] * (x[0] + x[mm - 1]);
903 for (
int ind = 1; ind < mid; ++ind)
905 const Number2 val0 = matrix[n_cols * n_columns + ind];
906 res0 += val0 * (x[ind] + x[mm - 1 - ind]);
914 out[stride_out * n_cols] += res0;
916 out[stride_out * n_cols] = res0;
937 for (
int col = 0; col < n_cols; ++col)
941 if (transpose_matrix ==
true)
944 val1 = matrix[nn - 1 - col];
948 val0 = matrix[col * n_columns];
949 val1 = matrix[(nn - col - 1) * n_columns];
955 res0 -= val1 * x[mm - 1];
956 res1 -= val0 * x[mm - 1];
957 for (
int ind = 1; ind < mid; ++ind)
959 if (transpose_matrix ==
true)
961 val0 = matrix[ind * n_columns + col];
962 val1 = matrix[ind * n_columns + nn - 1 - col];
966 val0 = matrix[col * n_columns + ind];
967 val1 = matrix[(nn - col - 1) * n_columns + ind];
969 res0 += val0 * x[ind];
970 res1 += val1 * x[ind];
971 res0 -= val1 * x[mm - 1 - ind];
972 res1 -= val0 * x[mm - 1 - ind];
976 res0 = res1 = Number();
979 if (transpose_matrix ==
true)
980 val0 = matrix[mid * n_columns + col];
982 val0 = matrix[col * n_columns + mid];
983 const Number tmp = val0 * x[mid];
989 out[stride_out * col] += res0;
990 out[stride_out * (nn - 1 - col)] += res1;
994 out[stride_out * col] = res0;
995 out[stride_out * (nn - 1 - col)] = res1;
1002 if (transpose_matrix ==
true)
1003 val0 = matrix[n_cols];
1005 val0 = matrix[n_cols * n_columns];
1006 res0 = val0 * (x[0] - x[mm - 1]);
1007 for (
int ind = 1; ind < mid; ++ind)
1009 if (transpose_matrix ==
true)
1010 val0 = matrix[ind * n_columns + n_cols];
1012 val0 = matrix[n_cols * n_columns + ind];
1013 Number in1 = val0 * (x[ind] - x[mm - 1 - ind]);
1017 out[stride_out * n_cols] += res0;
1019 out[stride_out * n_cols] = res0;
1026 for (
int col = 0; col < n_cols; ++col)
1030 if (transpose_matrix ==
true)
1033 val1 = matrix[nn - 1 - col];
1037 val0 = matrix[col * n_columns];
1038 val1 = matrix[(col + 1) * n_columns - 1];
1044 res0 += val1 * x[mm - 1];
1045 res1 += val0 * x[mm - 1];
1046 for (
int ind = 1; ind < mid; ++ind)
1048 if (transpose_matrix ==
true)
1050 val0 = matrix[ind * n_columns + col];
1051 val1 = matrix[ind * n_columns + nn - 1 - col];
1055 val0 = matrix[col * n_columns + ind];
1056 val1 = matrix[(col + 1) * n_columns - 1 - ind];
1058 res0 += val0 * x[ind];
1059 res1 += val1 * x[ind];
1060 res0 += val1 * x[mm - 1 - ind];
1061 res1 += val0 * x[mm - 1 - ind];
1065 res0 = res1 = Number();
1068 if (transpose_matrix ==
true)
1069 val0 = matrix[mid * n_columns + col];
1071 val0 = matrix[col * n_columns + mid];
1072 const Number tmp = val0 * x[mid];
1078 out[stride_out * col] += res0;
1079 out[stride_out * (nn - 1 - col)] += res1;
1083 out[stride_out * col] = res0;
1084 out[stride_out * (nn - 1 - col)] = res1;
1091 if (transpose_matrix ==
true)
1092 val0 = matrix[n_cols];
1094 val0 = matrix[n_cols * n_columns];
1097 res0 = val0 * (x[0] + x[mm - 1]);
1098 for (
int ind = 1; ind < mid; ++ind)
1100 if (transpose_matrix ==
true)
1101 val0 = matrix[ind * n_columns + n_cols];
1103 val0 = matrix[n_cols * n_columns + ind];
1104 Number in1 = val0 * (x[ind] + x[mm - 1 - ind]);
1112 if (transpose_matrix ==
true)
1113 val0 = matrix[mid * n_columns + n_cols];
1115 val0 = matrix[n_cols * n_columns + mid];
1116 res0 += val0 * x[mid];
1119 out[stride_out * n_cols] += res0;
1121 out[stride_out * n_cols] = res0;
1163 int n_rows_runtime = 0,
1164 int n_columns_runtime = 0,
1165 int stride_in_runtime = 0,
1166 int stride_out_runtime = 0)
1168 static_assert(n_rows_static >= 0 && n_columns_static >= 0,
1169 "Negative loop ranges are not allowed!");
1171 const int n_rows = n_rows_static == 0 ? n_rows_runtime : n_rows_static;
1172 const int n_columns =
1173 n_rows_static == 0 ? n_columns_runtime : n_columns_static;
1174 const int stride_in =
1175 stride_in_static == 0 ? stride_in_runtime : stride_in_static;
1176 const int stride_out =
1177 stride_out_static == 0 ? stride_out_runtime : stride_out_static;
1179 Assert(n_rows > 0 && n_columns > 0,
1181 std::to_string(n_rows) +
", " +
1182 std::to_string(n_columns) +
" was passed!"));
1184 const int mm = transpose_matrix ? n_rows : n_columns,
1185 nn = transpose_matrix ? n_columns : n_rows;
1186 const int n_half = nn / 2;
1187 const int m_half = mm / 2;
1189 constexpr int array_length =
1190 (n_rows_static == 0) ?
1193 (1 + (transpose_matrix ? n_rows_static : n_columns_static) / 2);
1194 const int offset = (n_columns + 1) / 2;
1198 std::array<Number, array_length> xp, xm;
1199 for (
int i = 0; i < m_half; ++i)
1203 xp[i] = in[stride_in * i] - in[stride_in * (mm - 1 - i)];
1204 xm[i] = in[stride_in * i] + in[stride_in * (mm - 1 - i)];
1208 xp[i] = in[stride_in * i] + in[stride_in * (mm - 1 - i)];
1209 xm[i] = in[stride_in * i] - in[stride_in * (mm - 1 - i)];
1212 Number xmid = in[stride_in * m_half];
1213 for (
int col = 0; col < n_half; ++col)
1218 if (transpose_matrix ==
true)
1220 r0 = matrix[col] * xp[0];
1221 r1 = matrix[(n_rows - 1) * offset + col] * xm[0];
1225 r0 = matrix[col * offset] * xp[0];
1226 r1 = matrix[(n_rows - 1 - col) * offset] * xm[0];
1228 for (
int ind = 1; ind < m_half; ++ind)
1230 if (transpose_matrix ==
true)
1232 r0 += matrix[ind * offset + col] * xp[ind];
1233 r1 += matrix[(n_rows - 1 - ind) * offset + col] * xm[ind];
1237 r0 += matrix[col * offset + ind] * xp[ind];
1238 r1 += matrix[(n_rows - 1 - col) * offset + ind] * xm[ind];
1244 if (mm % 2 == 1 && transpose_matrix ==
true)
1247 r1 += matrix[m_half * offset + col] * xmid;
1249 r0 += matrix[m_half * offset + col] * xmid;
1251 else if (mm % 2 == 1 &&
1254 r0 += matrix[col * offset + m_half] * xmid;
1258 out[stride_out * col] += r0 + r1;
1260 transpose_matrix ==
false)
1261 out[stride_out * (nn - 1 - col)] += r1 - r0;
1263 out[stride_out * (nn - 1 - col)] += r0 - r1;
1267 out[stride_out * col] = r0 + r1;
1269 transpose_matrix ==
false)
1270 out[stride_out * (nn - 1 - col)] = r1 - r0;
1272 out[stride_out * (nn - 1 - col)] = r0 - r1;
1276 nn % 2 == 1 && mm % 2 == 1 && mm > 3)
1279 out[stride_out * n_half] += matrix[m_half * offset + n_half] * xmid;
1281 out[stride_out * n_half] = matrix[m_half * offset + n_half] * xmid;
1283 else if (transpose_matrix ==
true && nn % 2 == 1)
1288 r0 = matrix[n_half] * xp[0];
1289 for (
int ind = 1; ind < m_half; ++ind)
1290 r0 += matrix[ind * offset + n_half] * xp[ind];
1295 r0 += matrix[m_half * offset + n_half] * xmid;
1298 out[stride_out * n_half] += r0;
1300 out[stride_out * n_half] = r0;
1302 else if (transpose_matrix ==
false && nn % 2 == 1)
1309 r0 = matrix[n_half * offset] * xm[0];
1310 for (
int ind = 1; ind < m_half; ++ind)
1311 r0 += matrix[n_half * offset + ind] * xm[ind];
1315 r0 = matrix[n_half * offset] * xp[0];
1316 for (
int ind = 1; ind < m_half; ++ind)
1317 r0 += matrix[n_half * offset + ind] * xp[ind];
1324 r0 += matrix[n_half * offset + m_half] * xmid;
1327 out[stride_out * n_half] += r0;
1329 out[stride_out * n_half] = r0;
1398 static_assert(n_rows > 0 && n_columns > 0,
1399 "Specialization requires n_rows, n_columns > 0");
1401 constexpr bool evaluate_antisymmetric =
1404 constexpr int mm = transpose_matrix ? n_rows : n_columns,
1405 nn = transpose_matrix ? n_columns : n_rows;
1406 constexpr int n_half = nn / 2;
1407 constexpr int m_half = mm / 2;
1409 if (transpose_matrix)
1411 std::array<Number, mm> x;
1412 for (
unsigned int i = 0; i < mm; ++i)
1413 x[i] = in[stride_in * i];
1414 for (
unsigned int col = 0; col < n_half; ++col)
1419 r0 = matrix[col] * x[0];
1420 r1 = matrix[col + n_columns] * x[1];
1421 for (
unsigned int ind = 1; ind < m_half; ++ind)
1423 r0 += matrix[col + 2 * ind * n_columns] * x[2 * ind];
1425 matrix[col + (2 * ind + 1) * n_columns] * x[2 * ind + 1];
1431 r0 += matrix[col + (mm - 1) * n_columns] * x[mm - 1];
1434 out[stride_out * col] += r0 + r1;
1435 if (evaluate_antisymmetric)
1436 out[stride_out * (nn - 1 - col)] += r1 - r0;
1438 out[stride_out * (nn - 1 - col)] += r0 - r1;
1442 out[stride_out * col] = r0 + r1;
1443 if (evaluate_antisymmetric)
1444 out[stride_out * (nn - 1 - col)] = r1 - r0;
1446 out[stride_out * (nn - 1 - col)] = r0 - r1;
1452 const unsigned int shift = evaluate_antisymmetric ? 1 : 0;
1455 r0 = matrix[n_half + shift * n_columns] * x[shift];
1456 for (
unsigned int ind = 1; ind < m_half; ++ind)
1457 r0 += matrix[n_half + (2 * ind + shift) * n_columns] *
1462 if (!evaluate_antisymmetric && mm % 2 == 1)
1463 r0 += matrix[n_half + (mm - 1) * n_columns] * x[mm - 1];
1465 out[stride_out * n_half] += r0;
1467 out[stride_out * n_half] = r0;
1472 std::array<Number, m_half + 1> xp, xm;
1473 for (
int i = 0; i < m_half; ++i)
1474 if (!evaluate_antisymmetric)
1476 xp[i] = in[stride_in * i] + in[stride_in * (mm - 1 - i)];
1477 xm[i] = in[stride_in * i] - in[stride_in * (mm - 1 - i)];
1481 xp[i] = in[stride_in * i] - in[stride_in * (mm - 1 - i)];
1482 xm[i] = in[stride_in * i] + in[stride_in * (mm - 1 - i)];
1485 xp[m_half] = in[stride_in * m_half];
1486 for (
unsigned int col = 0; col < n_half; ++col)
1491 r0 = matrix[2 * col * n_columns] * xp[0];
1492 r1 = matrix[(2 * col + 1) * n_columns] * xm[0];
1493 for (
unsigned int ind = 1; ind < m_half; ++ind)
1495 r0 += matrix[2 * col * n_columns + ind] * xp[ind];
1496 r1 += matrix[(2 * col + 1) * n_columns + ind] * xm[ind];
1503 if (evaluate_antisymmetric)
1504 r1 += matrix[(2 * col + 1) * n_columns + m_half] * xp[m_half];
1506 r0 += matrix[2 * col * n_columns + m_half] * xp[m_half];
1510 out[stride_out * (2 * col)] += r0;
1511 out[stride_out * (2 * col + 1)] += r1;
1515 out[stride_out * (2 * col)] = r0;
1516 out[stride_out * (2 * col + 1)] = r1;
1524 r0 = matrix[(nn - 1) * n_columns] * xp[0];
1525 for (
unsigned int ind = 1; ind < m_half; ++ind)
1526 r0 += matrix[(nn - 1) * n_columns + ind] * xp[ind];
1530 if (mm % 2 == 1 && !evaluate_antisymmetric)
1531 r0 += matrix[(nn - 1) * n_columns + m_half] * xp[m_half];
1533 out[stride_out * (nn - 1)] += r0;
1535 out[stride_out * (nn - 1)] = r0;