poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/reim4/reim4_arithmetic_avx2.c
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/reim4/reim4_arithmetic_avx2.cRaw
1#include <assert.h>
2#include <immintrin.h>
3
4#include "reim4_arithmetic.h"
5
6void reim4_extract_1blk_from_reim_avx(uint64_t m, uint64_t blk,
7 double* const dst, // nrows * 8 doubles
8 const double* const src // a contiguous array of nrows reim vectors
9) {
10 assert(blk < (m >> 2));
11 const double* src_ptr = src + (blk << 2);
12 double* dst_ptr = dst;
13 _mm256_storeu_pd(dst_ptr, _mm256_loadu_pd(src_ptr));
14 _mm256_storeu_pd(dst_ptr + 4, _mm256_loadu_pd(src_ptr + m));
15}
16
17void reim4_extract_1blk_from_contiguous_reim_avx(uint64_t m, uint64_t nrows, uint64_t blk, double* const dst,
18 const double* const src) {
19 assert(blk < (m >> 2));
20 const double* src_ptr = src + (blk << 2);
21 double* dst_ptr = dst;
22 for (uint64_t i = 0; i < nrows * 2; ++i) {
23 _mm256_storeu_pd(dst_ptr, _mm256_loadu_pd(src_ptr));
24 dst_ptr += 4;
25 src_ptr += m;
26 }
27}
28
29EXPORT void reim4_extract_1blk_from_contiguous_reim_sl_avx(uint64_t m, uint64_t sl, uint64_t nrows, uint64_t blk,
30 double* const dst, const double* const src) {
31 assert(blk < (m >> 2));
32 const double* src_ptr = src + (blk << 2);
33 double* dst_ptr = dst;
34 for (uint64_t i = 0; i < nrows; ++i) {
35 _mm256_storeu_pd(dst_ptr, _mm256_loadu_pd(src_ptr));
36 _mm256_storeu_pd(dst_ptr + 4, _mm256_loadu_pd(src_ptr + m));
37 dst_ptr += 8;
38 src_ptr += sl;
39 }
40}
41
42void reim4_save_1blk_to_reim_avx(uint64_t m, uint64_t blk,
43 double* dst, // 1 reim vector of length m
44 const double* src // 8 doubles
45) {
46 assert(blk < (m >> 2));
47 const double* src_ptr = src;
48 double* dst_ptr = dst + (blk << 2);
49 _mm256_storeu_pd(dst_ptr, _mm256_loadu_pd(src_ptr));
50 _mm256_storeu_pd(dst_ptr + m, _mm256_loadu_pd(src_ptr + 4));
51}
52
53void reim4_add_1blk_to_reim_avx(uint64_t m, uint64_t blk,
54 double* dst, // 1 reim vector of length m
55 const double* src // 8 doubles
56) {
57 assert(blk < (m >> 2));
58 const double* src_ptr = src;
59 double* dst_ptr = dst + (blk << 2);
60
61 __m256d s0 = _mm256_loadu_pd(src_ptr);
62 __m256d d0 = _mm256_loadu_pd(dst_ptr);
63 _mm256_storeu_pd(dst_ptr, _mm256_add_pd(s0, d0));
64
65 __m256d s1 = _mm256_loadu_pd(src_ptr + 4);
66 __m256d d1 = _mm256_loadu_pd(dst_ptr + m);
67 _mm256_storeu_pd(dst_ptr + m, _mm256_add_pd(s1, d1));
68}
69
70__always_inline void cplx_prod(__m256d* re1, __m256d* re2, __m256d* im, const double* const u_ptr,
71 const double* const v_ptr) {
72 const __m256d a = _mm256_loadu_pd(u_ptr);
73 const __m256d c = _mm256_loadu_pd(v_ptr);
74 *re1 = _mm256_fmadd_pd(a, c, *re1);
75
76 const __m256d b = _mm256_loadu_pd(u_ptr + 4);
77 *im = _mm256_fmadd_pd(b, c, *im);
78
79 const __m256d d = _mm256_loadu_pd(v_ptr + 4);
80 *re2 = _mm256_fmadd_pd(b, d, *re2);
81 *im = _mm256_fmadd_pd(a, d, *im);
82}
83
84void reim4_vec_mat1col_product_avx2(const uint64_t nrows,
85 double* const dst, // 8 doubles
86 const double* const u, // nrows * 8 doubles
87 const double* const v // nrows * 8 doubles
88) {
89 __m256d re1 = _mm256_setzero_pd();
90 __m256d re2 = _mm256_setzero_pd();
91 __m256d im1 = _mm256_setzero_pd();
92 __m256d im2 = _mm256_setzero_pd();
93
94 const double* u_ptr = u;
95 const double* v_ptr = v;
96 for (uint64_t i = 0; i < nrows; ++i) {
97 const __m256d a = _mm256_loadu_pd(u_ptr);
98 const __m256d c = _mm256_loadu_pd(v_ptr);
99 re1 = _mm256_fmadd_pd(a, c, re1);
100
101 const __m256d b = _mm256_loadu_pd(u_ptr + 4);
102 im2 = _mm256_fmadd_pd(b, c, im2);
103
104 const __m256d d = _mm256_loadu_pd(v_ptr + 4);
105 re2 = _mm256_fmadd_pd(b, d, re2);
106 im1 = _mm256_fmadd_pd(a, d, im1);
107
108 u_ptr += 8;
109 v_ptr += 8;
110 }
111
112 _mm256_storeu_pd(dst, _mm256_sub_pd(re1, re2));
113 _mm256_storeu_pd(dst + 4, _mm256_add_pd(im1, im2));
114}
115
116EXPORT void reim4_vec_mat2cols_product_avx2(const uint64_t nrows,
117 double* const dst, // 16 doubles
118 const double* const u, // nrows * 16 doubles
119 const double* const v // nrows * 16 doubles
120) {
121 __m256d re1 = _mm256_setzero_pd();
122 __m256d im1 = _mm256_setzero_pd();
123 __m256d re2 = _mm256_setzero_pd();
124 __m256d im2 = _mm256_setzero_pd();
125
126 __m256d ur, ui, ar, ai, br, bi;
127 for (uint64_t i = 0; i < nrows; ++i) {
128 ur = _mm256_loadu_pd(u + 8 * i);
129 ui = _mm256_loadu_pd(u + 8 * i + 4);
130 ar = _mm256_loadu_pd(v + 16 * i);
131 ai = _mm256_loadu_pd(v + 16 * i + 4);
132 br = _mm256_loadu_pd(v + 16 * i + 8);
133 bi = _mm256_loadu_pd(v + 16 * i + 12);
134 re1 = _mm256_fmsub_pd(ui, ai, re1);
135 re2 = _mm256_fmsub_pd(ui, bi, re2);
136 im1 = _mm256_fmadd_pd(ur, ai, im1);
137 im2 = _mm256_fmadd_pd(ur, bi, im2);
138 re1 = _mm256_fmsub_pd(ur, ar, re1);
139 re2 = _mm256_fmsub_pd(ur, br, re2);
140 im1 = _mm256_fmadd_pd(ui, ar, im1);
141 im2 = _mm256_fmadd_pd(ui, br, im2);
142 }
143 _mm256_storeu_pd(dst, re1);
144 _mm256_storeu_pd(dst + 4, im1);
145 _mm256_storeu_pd(dst + 8, re2);
146 _mm256_storeu_pd(dst + 12, im2);
147}