/src/Simd/src/Simd/SimdBaseWinograd2.cpp
Line | Count | Source |
1 | | /* |
2 | | * Simd Library (http://ermig1979.github.io/Simd). |
3 | | * |
4 | | * Copyright (c) 2011-2021 Yermalayeu Ihar. |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to deal |
8 | | * in the Software without restriction, including without limitation the rights |
9 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
10 | | * copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
21 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | #include "Simd/SimdMemory.h" |
25 | | #include "Simd/SimdWinograd.h" |
26 | | |
27 | | namespace Simd |
28 | | { |
29 | | #if defined(SIMD_SYNET_ENABLE) |
30 | | namespace Base |
31 | | { |
32 | | void WinogradKernel2x2Block2x2SetFilter(const float* src, size_t size, float* dst, SimdBool trans) |
33 | 0 | { |
34 | 0 | if (trans) |
35 | 0 | { |
36 | 0 | for (size_t i = 0; i < size; i += 1) |
37 | 0 | Base::WinogradKernel2x2Block2x2SetFilter1t(src + i, dst + i, size); |
38 | 0 | } |
39 | 0 | else |
40 | 0 | { |
41 | 0 | for (size_t i = 0; i < size; i += 1, src += 4, dst += 1) |
42 | 0 | Base::WinogradKernel2x2Block2x2SetFilter1n(src, dst, size); |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | //----------------------------------------------------------------------- |
47 | | |
48 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetInput1(const float src[16], float* dst, size_t stride) |
49 | 0 | { |
50 | 0 | dst[0 * stride] = src[0] - src[1] - src[3] + src[4]; |
51 | 0 | dst[1 * stride] = src[1] - src[4]; |
52 | 0 | dst[2 * stride] = src[2] - src[1] + src[4] - src[5]; |
53 | 0 | dst[3 * stride] = src[3] - src[4]; |
54 | 0 | dst[4 * stride] = src[4]; |
55 | 0 | dst[5 * stride] = src[5] - src[4]; |
56 | 0 | dst[6 * stride] = src[4] - src[3] + src[6] - src[7]; |
57 | 0 | dst[7 * stride] = src[7] - src[4]; |
58 | 0 | dst[8 * stride] = src[4] - src[5] + src[8] - src[7]; |
59 | 0 | } |
60 | | |
61 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetInput1n(const float* src, size_t srcStride, float* dst, size_t dstStride) |
62 | 0 | { |
63 | 0 | float tmp[9]; |
64 | 0 | tmp[0] = src[0 * srcStride + 0]; |
65 | 0 | tmp[1] = src[0 * srcStride + 1]; |
66 | 0 | tmp[2] = src[0 * srcStride + 2]; |
67 | 0 | tmp[3] = src[1 * srcStride + 0]; |
68 | 0 | tmp[4] = src[1 * srcStride + 1]; |
69 | 0 | tmp[5] = src[1 * srcStride + 2]; |
70 | 0 | tmp[6] = src[2 * srcStride + 0]; |
71 | 0 | tmp[7] = src[2 * srcStride + 1]; |
72 | 0 | tmp[8] = src[2 * srcStride + 2]; |
73 | |
|
74 | 0 | WinogradKernel2x2Block2x2SetInput1(tmp, dst, dstStride); |
75 | 0 | } |
76 | | |
77 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetInput1n(const float* src, size_t srcStride, size_t rowB, size_t rowE, size_t colB, size_t colE, float* dst, size_t dstStride) |
78 | 0 | { |
79 | 0 | float tmp[9] = { 0 }; |
80 | 0 | for (size_t row = rowB; row < rowE; ++row) |
81 | 0 | for (size_t col = colB; col < colE; ++col) |
82 | 0 | tmp[row * 3 + col] = src[row * srcStride + col]; |
83 | 0 | WinogradKernel2x2Block2x2SetInput1(tmp, dst, dstStride); |
84 | 0 | } |
85 | | |
86 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetInput1t(const float* src, size_t srcW, size_t srcC, float* dst, size_t dstStride) |
87 | 0 | { |
88 | 0 | size_t srcS = srcW * srcC; |
89 | 0 | for (size_t c = 0; c < srcC; ++c, src++, dst++) |
90 | 0 | { |
91 | 0 | float tmp[9]; |
92 | 0 | tmp[0] = src[0 * srcS + 0 * srcC]; |
93 | 0 | tmp[1] = src[0 * srcS + 1 * srcC]; |
94 | 0 | tmp[2] = src[0 * srcS + 2 * srcC]; |
95 | 0 | tmp[3] = src[1 * srcS + 0 * srcC]; |
96 | 0 | tmp[4] = src[1 * srcS + 1 * srcC]; |
97 | 0 | tmp[5] = src[1 * srcS + 2 * srcC]; |
98 | 0 | tmp[6] = src[2 * srcS + 0 * srcC]; |
99 | 0 | tmp[7] = src[2 * srcS + 1 * srcC]; |
100 | 0 | tmp[8] = src[2 * srcS + 2 * srcC]; |
101 | 0 | WinogradKernel2x2Block2x2SetInput1(tmp, dst, dstStride); |
102 | 0 | } |
103 | 0 | } |
104 | | |
105 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetInput1t(const float* src, size_t srcW, size_t srcC, size_t rowB, size_t rowE, size_t colB, size_t colE, float* dst, size_t dstStride) |
106 | 0 | { |
107 | 0 | size_t srcS = srcW * srcC; |
108 | 0 | for (size_t c = 0; c < srcC; ++c, src++, dst++) |
109 | 0 | { |
110 | 0 | float tmp[9] = { 0 }; |
111 | 0 | for (size_t row = rowB; row < rowE; ++row) |
112 | 0 | for (size_t col = colB; col < colE; ++col) |
113 | 0 | tmp[row * 3 + col] = src[row * srcS + col * srcC]; |
114 | 0 | WinogradKernel2x2Block2x2SetInput1(tmp, dst, dstStride); |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | | void WinogradKernel2x2Block2x2SetInput(const float* src, size_t srcChannels, size_t srcHeight, size_t srcWidth, |
119 | | size_t padY, size_t padX, size_t padH, size_t padW, float* dst, size_t dstStride, SimdBool trans) |
120 | 0 | { |
121 | 0 | assert(padY == padX && padW == padH && (padY + padH == 0 || padY + padH == 1)); |
122 | 0 | size_t dstHeight = srcHeight - 1 + padY + padH; |
123 | 0 | size_t dstWidth = srcWidth - 1 + padX + padW; |
124 | 0 | size_t dstHeightFull = AlignLo(dstHeight, 2); |
125 | 0 | size_t dstWidthFull = AlignLo(dstWidth, 2); |
126 | 0 | size_t noseW = Simd::Min<size_t>(3, dstWidth + 1); |
127 | 0 | size_t noseH = Simd::Min<size_t>(3, dstHeight + 1); |
128 | 0 | size_t startY = padY ? 2 : 0; |
129 | 0 | size_t startX = padX ? 2 : 0; |
130 | 0 | if (padY || padH) |
131 | 0 | { |
132 | 0 | if (dstHeight == dstHeightFull) |
133 | 0 | dstHeightFull -= 2; |
134 | 0 | if (dstWidth == dstWidthFull) |
135 | 0 | dstWidthFull -= 2; |
136 | 0 | if(padY) |
137 | 0 | src -= (srcWidth + 1) * (trans ? srcChannels : 1); |
138 | 0 | } |
139 | 0 | size_t tailW = dstWidth - dstWidthFull + (padW ? 0 : 1); |
140 | 0 | size_t tailH = dstHeight - dstHeightFull + (padH ? 0 : 1); |
141 | 0 | if (trans) |
142 | 0 | { |
143 | 0 | size_t row = 0, col = 0; |
144 | 0 | if (padY) |
145 | 0 | { |
146 | 0 | if (padX) |
147 | 0 | WinogradKernel2x2Block2x2SetInput1t(src, srcWidth, srcChannels, 1, noseH, 1, noseW, dst, dstStride), dst += srcChannels; |
148 | 0 | for (col = startX; col < dstWidthFull; col += 2) |
149 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + col * srcChannels, srcWidth, srcChannels, 1, noseH, 0, 3, dst, dstStride), dst += srcChannels; |
150 | 0 | if (col < dstWidth) |
151 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + col * srcChannels, srcWidth, srcChannels, 1, noseH, 0, tailW, dst, dstStride), dst += srcChannels; |
152 | 0 | } |
153 | 0 | for (row = startY; row < dstHeightFull; row += 2) |
154 | 0 | { |
155 | 0 | if (padX) |
156 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + row * srcWidth * srcChannels, srcWidth, srcChannels, 0, 3, 1, noseW, dst, dstStride), dst += srcChannels; |
157 | 0 | for (col = startX; col < dstWidthFull; col += 2) |
158 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, dst, dstStride), dst += srcChannels; |
159 | 0 | if (col < dstWidth) |
160 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, 0, 3, 0, tailW, dst, dstStride), dst += srcChannels; |
161 | 0 | } |
162 | 0 | if (row < dstHeight) |
163 | 0 | { |
164 | 0 | if (padX) |
165 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + row * srcWidth * srcChannels, srcWidth, srcChannels, 0, tailH, 1, noseW, dst, dstStride), dst += srcChannels; |
166 | 0 | for (col = startX; col < dstWidthFull; col += 2) |
167 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, 0, tailH, 0, 3, dst, dstStride), dst += srcChannels; |
168 | 0 | if (col < dstWidth) |
169 | 0 | WinogradKernel2x2Block2x2SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, 0, tailH, 0, tailW, dst, dstStride), dst += srcChannels; |
170 | 0 | } |
171 | 0 | } |
172 | 0 | else |
173 | 0 | { |
174 | 0 | for (size_t c = 0; c < srcChannels; ++c) |
175 | 0 | { |
176 | 0 | size_t row = 0, col = 0; |
177 | 0 | if (padY) |
178 | 0 | { |
179 | 0 | if (padX) |
180 | 0 | WinogradKernel2x2Block2x2SetInput1n(src, srcWidth, 1, noseH, 1, noseW, dst++, dstStride); |
181 | 0 | for (col = startX; col < dstWidthFull; col += 2) |
182 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + col, srcWidth, 1, noseH, 0, 3, dst++, dstStride); |
183 | 0 | if (col < dstWidth) |
184 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + col, srcWidth, 1, noseH, 0, tailW, dst++, dstStride); |
185 | 0 | } |
186 | 0 | for (row = startY; row < dstHeightFull; row += 2) |
187 | 0 | { |
188 | 0 | if (padX) |
189 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + row * srcWidth, srcWidth, 0, 3, 1, noseW, dst++, dstStride); |
190 | 0 | for (col = startX; col < dstWidthFull; col += 2) |
191 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + row * srcWidth + col, srcWidth, dst++, dstStride); |
192 | 0 | if (col < dstWidth) |
193 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + row * srcWidth + col, srcWidth, 0, 3, 0, tailW, dst++, dstStride); |
194 | 0 | } |
195 | 0 | if (row < dstHeight) |
196 | 0 | { |
197 | 0 | if (padX) |
198 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + row * srcWidth, srcWidth, 0, tailH, 1, noseW, dst++, dstStride); |
199 | 0 | for (col = startX; col < dstWidthFull; col += 2) |
200 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + row * srcWidth + col, srcWidth, 0, tailH, 0, 3, dst++, dstStride); |
201 | 0 | if (col < dstWidth) |
202 | 0 | WinogradKernel2x2Block2x2SetInput1n(src + row * srcWidth + col, srcWidth, 0, tailH, 0, tailW, dst++, dstStride); |
203 | 0 | } |
204 | 0 | src += srcWidth * srcHeight; |
205 | 0 | } |
206 | 0 | } |
207 | 0 | } |
208 | | |
209 | | //----------------------------------------------------------------------- |
210 | | |
211 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetOutput1(const float* src, size_t stride, float dst[4]) |
212 | 0 | { |
213 | 0 | float s[9]; |
214 | 0 | s[0] = src[0 * stride]; |
215 | 0 | s[1] = src[1 * stride]; |
216 | 0 | s[2] = src[2 * stride]; |
217 | 0 | s[3] = src[3 * stride]; |
218 | 0 | s[4] = src[4 * stride]; |
219 | 0 | s[5] = src[5 * stride]; |
220 | 0 | s[6] = src[6 * stride]; |
221 | 0 | s[7] = src[7 * stride]; |
222 | 0 | s[8] = src[8 * stride]; |
223 | |
|
224 | 0 | dst[0] = s[0] + s[1] + s[3] + s[4]; |
225 | 0 | dst[1] = s[1] + s[2] + s[4] + s[5]; |
226 | 0 | dst[2] = s[3] + s[4] + s[6] + s[7]; |
227 | 0 | dst[3] = s[4] + s[5] + s[7] + s[8]; |
228 | 0 | } |
229 | | |
230 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetOutput1n(const float* src, size_t srcStride, float* dst, size_t dstStride) |
231 | 0 | { |
232 | 0 | float tmp[4]; |
233 | 0 | WinogradKernel2x2Block2x2SetOutput1(src, srcStride, tmp); |
234 | 0 | dst[0 * dstStride + 0] = tmp[0]; |
235 | 0 | dst[0 * dstStride + 1] = tmp[1]; |
236 | 0 | dst[1 * dstStride + 0] = tmp[2]; |
237 | 0 | dst[1 * dstStride + 1] = tmp[3]; |
238 | 0 | } |
239 | | |
240 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetOutput1n(const float* src, size_t srcStride, float* dst, size_t dstStride, size_t rowE, size_t colE) |
241 | 0 | { |
242 | 0 | float tmp[4]; |
243 | 0 | WinogradKernel2x2Block2x2SetOutput1(src, srcStride, tmp); |
244 | 0 | for (size_t row = 0; row < rowE; ++row) |
245 | 0 | for (size_t col = 0; col < colE; ++col) |
246 | 0 | dst[row * dstStride + col] = tmp[row * 2 + col]; |
247 | 0 | } |
248 | | |
249 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetOutput1t(const float* src, size_t srcStride, float* dst, size_t dstW, size_t dstC) |
250 | 0 | { |
251 | 0 | size_t dstS = dstW * dstC; |
252 | 0 | for (size_t d = 0; d < dstC; ++d, src++, dst++) |
253 | 0 | { |
254 | 0 | float tmp[4]; |
255 | 0 | WinogradKernel2x2Block2x2SetOutput1(src, srcStride, tmp); |
256 | 0 | dst[0 * dstS + 0 * dstC] = tmp[0]; |
257 | 0 | dst[0 * dstS + 1 * dstC] = tmp[1]; |
258 | 0 | dst[1 * dstS + 0 * dstC] = tmp[2]; |
259 | 0 | dst[1 * dstS + 1 * dstC] = tmp[3]; |
260 | 0 | } |
261 | 0 | } |
262 | | |
263 | | SIMD_INLINE void WinogradKernel2x2Block2x2SetOutput1t(const float* src, size_t srcStride, float* dst, size_t dstW, size_t dstC, size_t rowE, size_t colE) |
264 | 0 | { |
265 | 0 | size_t dstS = dstW * dstC; |
266 | 0 | for (size_t d = 0; d < dstC; ++d, src++, dst++) |
267 | 0 | { |
268 | 0 | float tmp[4]; |
269 | 0 | WinogradKernel2x2Block2x2SetOutput1(src, srcStride, tmp); |
270 | 0 | for (size_t row = 0; row < rowE; ++row) |
271 | 0 | for (size_t col = 0; col < colE; ++col) |
272 | 0 | dst[row * dstS + col * dstC] = tmp[row * 2 + col]; |
273 | 0 | } |
274 | 0 | } |
275 | | |
276 | | void WinogradKernel2x2Block2x2SetOutput(const float* src, size_t srcStride, float* dst, size_t dstChannels, size_t dstHeight, size_t dstWidth, SimdBool trans) |
277 | 0 | { |
278 | 0 | size_t dstHeightFull = AlignLo(dstHeight, 2); |
279 | 0 | size_t dstWidthFull = AlignLo(dstWidth, 2); |
280 | 0 | if (trans) |
281 | 0 | { |
282 | 0 | size_t row, col; |
283 | 0 | for (row = 0; row < dstHeightFull; row += 2) |
284 | 0 | { |
285 | 0 | for (col = 0; col < dstWidthFull; col += 2) |
286 | 0 | WinogradKernel2x2Block2x2SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels), src += dstChannels; |
287 | 0 | if (col < dstWidth) |
288 | 0 | WinogradKernel2x2Block2x2SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels, 2, dstWidth - col), src += dstChannels; |
289 | 0 | } |
290 | 0 | if (row < dstHeight) |
291 | 0 | { |
292 | 0 | for (col = 0; col < dstWidthFull; col += 2) |
293 | 0 | WinogradKernel2x2Block2x2SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels, dstHeight - row, 2), src += dstChannels; |
294 | 0 | if (col < dstWidth) |
295 | 0 | WinogradKernel2x2Block2x2SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels, dstHeight - row, dstWidth - col), src += dstChannels; |
296 | 0 | } |
297 | 0 | } |
298 | 0 | else |
299 | 0 | { |
300 | 0 | for (size_t c = 0; c < dstChannels; ++c) |
301 | 0 | { |
302 | 0 | size_t row, col; |
303 | 0 | for (row = 0; row < dstHeightFull; row += 2) |
304 | 0 | { |
305 | 0 | for (col = 0; col < dstWidthFull; col += 2) |
306 | 0 | WinogradKernel2x2Block2x2SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth); |
307 | 0 | if (col < dstWidth) |
308 | 0 | WinogradKernel2x2Block2x2SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth, 2, dstWidth - col); |
309 | 0 | } |
310 | 0 | if (row < dstHeight) |
311 | 0 | { |
312 | 0 | for (col = 0; col < dstWidthFull; col += 2) |
313 | 0 | WinogradKernel2x2Block2x2SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth, dstHeight - row, 2); |
314 | 0 | if (col < dstWidth) |
315 | 0 | WinogradKernel2x2Block2x2SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth, dstHeight - row, dstWidth - col); |
316 | 0 | } |
317 | 0 | dst += dstHeight * dstWidth; |
318 | 0 | } |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | | //----------------------------------------------------------------------- |
323 | | |
324 | | void WinogradKernel2x2Block4x4SetFilter(const float* src, size_t size, float* dst, SimdBool trans) |
325 | 0 | { |
326 | 0 | if (trans) |
327 | 0 | { |
328 | 0 | for (size_t i = 0; i < size; i += 1) |
329 | 0 | Base::WinogradKernel2x2Block4x4SetFilter1t(src + i, dst + i, size); |
330 | 0 | } |
331 | 0 | else |
332 | 0 | { |
333 | 0 | for (size_t i = 0; i < size; i += 1, src += 4, dst += 1) |
334 | 0 | Base::WinogradKernel2x2Block4x4SetFilter1n(src, dst, size); |
335 | 0 | } |
336 | 0 | } |
337 | | |
338 | | //----------------------------------------------------------------------- |
339 | | |
340 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetInput1(const float src[25], float* dst, size_t stride) |
341 | 0 | { |
342 | 0 | float tmp[25]; |
343 | 0 | tmp[0] = 2 * src[0] - src[5] - 2 * src[10] + src[15]; |
344 | 0 | tmp[1] = 2 * src[1] - src[6] - 2 * src[11] + src[16]; |
345 | 0 | tmp[2] = 2 * src[2] - src[7] - 2 * src[12] + src[17]; |
346 | 0 | tmp[3] = 2 * src[3] - src[8] - 2 * src[13] + src[18]; |
347 | 0 | tmp[4] = 2 * src[4] - src[9] - 2 * src[14] + src[19]; |
348 | 0 | tmp[5] = src[15] - 2 * src[5] - src[10]; |
349 | 0 | tmp[6] = src[16] - 2 * src[6] - src[11]; |
350 | 0 | tmp[7] = src[17] - 2 * src[7] - src[12]; |
351 | 0 | tmp[8] = src[18] - 2 * src[8] - src[13]; |
352 | 0 | tmp[9] = src[19] - 2 * src[9] - src[14]; |
353 | 0 | tmp[10] = 2 * src[5] - 3 * src[10] + src[15]; |
354 | 0 | tmp[11] = 2 * src[6] - 3 * src[11] + src[16]; |
355 | 0 | tmp[12] = 2 * src[7] - 3 * src[12] + src[17]; |
356 | 0 | tmp[13] = 2 * src[8] - 3 * src[13] + src[18]; |
357 | 0 | tmp[14] = 2 * src[9] - 3 * src[14] + src[19]; |
358 | 0 | tmp[15] = src[15] - src[5]; |
359 | 0 | tmp[16] = src[16] - src[6]; |
360 | 0 | tmp[17] = src[17] - src[7]; |
361 | 0 | tmp[18] = src[18] - src[8]; |
362 | 0 | tmp[19] = src[19] - src[9]; |
363 | 0 | tmp[20] = 2 * src[5] - src[10] - 2 * src[15] + src[20]; |
364 | 0 | tmp[21] = 2 * src[6] - src[11] - 2 * src[16] + src[21]; |
365 | 0 | tmp[22] = 2 * src[7] - src[12] - 2 * src[17] + src[22]; |
366 | 0 | tmp[23] = 2 * src[8] - src[13] - 2 * src[18] + src[23]; |
367 | 0 | tmp[24] = 2 * src[9] - src[14] - 2 * src[19] + src[24]; |
368 | |
|
369 | 0 | dst[0 * stride] = 2 * tmp[0] - tmp[1] - 2 * tmp[2] + tmp[3]; |
370 | 0 | dst[1 * stride] = tmp[3] - 2 * tmp[1] - tmp[2]; |
371 | 0 | dst[2 * stride] = 2 * tmp[1] - 3 * tmp[2] + tmp[3]; |
372 | 0 | dst[3 * stride] = tmp[3] - tmp[1]; |
373 | 0 | dst[4 * stride] = 2 * tmp[1] - tmp[2] - 2 * tmp[3] + tmp[4]; |
374 | 0 | dst[5 * stride] = 2 * tmp[5] - tmp[6] - 2 * tmp[7] + tmp[8]; |
375 | 0 | dst[6 * stride] = tmp[8] - 2 * tmp[6] - tmp[7]; |
376 | 0 | dst[7 * stride] = 2 * tmp[6] - 3 * tmp[7] + tmp[8]; |
377 | 0 | dst[8 * stride] = tmp[8] - tmp[6]; |
378 | 0 | dst[9 * stride] = 2 * tmp[6] - tmp[7] - 2 * tmp[8] + tmp[9]; |
379 | 0 | dst[10 * stride] = 2 * tmp[10] - tmp[11] - 2 * tmp[12] + tmp[13]; |
380 | 0 | dst[11 * stride] = tmp[13] - 2 * tmp[11] - tmp[12]; |
381 | 0 | dst[12 * stride] = 2 * tmp[11] - 3 * tmp[12] + tmp[13]; |
382 | 0 | dst[13 * stride] = tmp[13] - tmp[11]; |
383 | 0 | dst[14 * stride] = 2 * tmp[11] - tmp[12] - 2 * tmp[13] + tmp[14]; |
384 | 0 | dst[15 * stride] = 2 * tmp[15] - tmp[16] - 2 * tmp[17] + tmp[18]; |
385 | 0 | dst[16 * stride] = tmp[18] - 2 * tmp[16] - tmp[17]; |
386 | 0 | dst[17 * stride] = 2 * tmp[16] - 3 * tmp[17] + tmp[18]; |
387 | 0 | dst[18 * stride] = tmp[18] - tmp[16]; |
388 | 0 | dst[19 * stride] = 2 * tmp[16] - tmp[17] - 2 * tmp[18] + tmp[19]; |
389 | 0 | dst[20 * stride] = 2 * tmp[20] - tmp[21] - 2 * tmp[22] + tmp[23]; |
390 | 0 | dst[21 * stride] = tmp[23] - 2 * tmp[21] - tmp[22]; |
391 | 0 | dst[22 * stride] = 2 * tmp[21] - 3 * tmp[22] + tmp[23]; |
392 | 0 | dst[23 * stride] = tmp[23] - tmp[21]; |
393 | 0 | dst[24 * stride] = 2 * tmp[21] - tmp[22] - 2 * tmp[23] + tmp[24]; |
394 | 0 | } |
395 | | |
396 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetInput1n(const float* src, size_t srcStride, float* dst, size_t dstStride) |
397 | 0 | { |
398 | 0 | float tmp[25]; |
399 | 0 | tmp[0] = src[0 * srcStride + 0]; |
400 | 0 | tmp[1] = src[0 * srcStride + 1]; |
401 | 0 | tmp[2] = src[0 * srcStride + 2]; |
402 | 0 | tmp[3] = src[0 * srcStride + 3]; |
403 | 0 | tmp[4] = src[0 * srcStride + 4]; |
404 | 0 | tmp[5] = src[1 * srcStride + 0]; |
405 | 0 | tmp[6] = src[1 * srcStride + 1]; |
406 | 0 | tmp[7] = src[1 * srcStride + 2]; |
407 | 0 | tmp[8] = src[1 * srcStride + 3]; |
408 | 0 | tmp[9] = src[1 * srcStride + 4]; |
409 | 0 | tmp[10] = src[2 * srcStride + 0]; |
410 | 0 | tmp[11] = src[2 * srcStride + 1]; |
411 | 0 | tmp[12] = src[2 * srcStride + 2]; |
412 | 0 | tmp[13] = src[2 * srcStride + 3]; |
413 | 0 | tmp[14] = src[2 * srcStride + 4]; |
414 | 0 | tmp[15] = src[3 * srcStride + 0]; |
415 | 0 | tmp[16] = src[3 * srcStride + 1]; |
416 | 0 | tmp[17] = src[3 * srcStride + 2]; |
417 | 0 | tmp[18] = src[3 * srcStride + 3]; |
418 | 0 | tmp[19] = src[3 * srcStride + 4]; |
419 | 0 | tmp[20] = src[4 * srcStride + 0]; |
420 | 0 | tmp[21] = src[4 * srcStride + 1]; |
421 | 0 | tmp[22] = src[4 * srcStride + 2]; |
422 | 0 | tmp[23] = src[4 * srcStride + 3]; |
423 | 0 | tmp[24] = src[4 * srcStride + 4]; |
424 | 0 | WinogradKernel2x2Block4x4SetInput1(tmp, dst, dstStride); |
425 | 0 | } |
426 | | |
427 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetInput1n(const float* src, size_t srcStride, size_t rowB, size_t rowE, size_t colB, size_t colE, float* dst, size_t dstStride) |
428 | 0 | { |
429 | 0 | float tmp[25] = { 0 }; |
430 | 0 | for (size_t row = rowB; row < rowE; ++row) |
431 | 0 | for (size_t col = colB; col < colE; ++col) |
432 | 0 | tmp[row * 5 + col] = src[row * srcStride + col]; |
433 | 0 | WinogradKernel2x2Block4x4SetInput1(tmp, dst, dstStride); |
434 | 0 | } |
435 | | |
436 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetInput1t(const float* src, size_t srcW, size_t srcC, float* dst, size_t dstStride) |
437 | 0 | { |
438 | 0 | size_t srcS = srcW * srcC; |
439 | 0 | for (size_t c = 0; c < srcC; ++c, src++, dst++) |
440 | 0 | { |
441 | 0 | float tmp[25]; |
442 | 0 | tmp[0] = src[0 * srcS + 0 * srcC]; |
443 | 0 | tmp[1] = src[0 * srcS + 1 * srcC]; |
444 | 0 | tmp[2] = src[0 * srcS + 2 * srcC]; |
445 | 0 | tmp[3] = src[0 * srcS + 3 * srcC]; |
446 | 0 | tmp[4] = src[0 * srcS + 4 * srcC]; |
447 | 0 | tmp[5] = src[1 * srcS + 0 * srcC]; |
448 | 0 | tmp[6] = src[1 * srcS + 1 * srcC]; |
449 | 0 | tmp[7] = src[1 * srcS + 2 * srcC]; |
450 | 0 | tmp[8] = src[1 * srcS + 3 * srcC]; |
451 | 0 | tmp[9] = src[1 * srcS + 4 * srcC]; |
452 | 0 | tmp[10] = src[2 * srcS + 0 * srcC]; |
453 | 0 | tmp[11] = src[2 * srcS + 1 * srcC]; |
454 | 0 | tmp[12] = src[2 * srcS + 2 * srcC]; |
455 | 0 | tmp[13] = src[2 * srcS + 3 * srcC]; |
456 | 0 | tmp[14] = src[2 * srcS + 4 * srcC]; |
457 | 0 | tmp[15] = src[3 * srcS + 0 * srcC]; |
458 | 0 | tmp[16] = src[3 * srcS + 1 * srcC]; |
459 | 0 | tmp[17] = src[3 * srcS + 2 * srcC]; |
460 | 0 | tmp[18] = src[3 * srcS + 3 * srcC]; |
461 | 0 | tmp[19] = src[3 * srcS + 4 * srcC]; |
462 | 0 | tmp[20] = src[4 * srcS + 0 * srcC]; |
463 | 0 | tmp[21] = src[4 * srcS + 1 * srcC]; |
464 | 0 | tmp[22] = src[4 * srcS + 2 * srcC]; |
465 | 0 | tmp[23] = src[4 * srcS + 3 * srcC]; |
466 | 0 | tmp[24] = src[4 * srcS + 4 * srcC]; |
467 | 0 | WinogradKernel2x2Block4x4SetInput1(tmp, dst, dstStride); |
468 | 0 | } |
469 | 0 | } |
470 | | |
471 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetInput1t(const float* src, size_t srcW, size_t srcC, size_t rowB, size_t rowE, size_t colB, size_t colE, float* dst, size_t dstStride) |
472 | 0 | { |
473 | 0 | size_t srcS = srcW * srcC; |
474 | 0 | for (size_t c = 0; c < srcC; ++c, src++, dst++) |
475 | 0 | { |
476 | 0 | float tmp[25] = { 0 }; |
477 | 0 | for (size_t row = rowB; row < rowE; ++row) |
478 | 0 | for (size_t col = colB; col < colE; ++col) |
479 | 0 | tmp[row * 5 + col] = src[row * srcS + col * srcC]; |
480 | 0 | WinogradKernel2x2Block4x4SetInput1(tmp, dst, dstStride); |
481 | 0 | } |
482 | 0 | } |
483 | | |
484 | | void WinogradKernel2x2Block4x4SetInput(const float* src, size_t srcChannels, size_t srcHeight, size_t srcWidth, |
485 | | size_t padY, size_t padX, size_t padH, size_t padW, float* dst, size_t dstStride, SimdBool trans) |
486 | 0 | { |
487 | 0 | assert(padY == padX && padW == padH && (padY + padH == 0 || padY + padH == 1)); |
488 | 0 | size_t dstHeight = srcHeight - 1 + padY + padH; |
489 | 0 | size_t dstWidth = srcWidth - 1 + padX + padW; |
490 | 0 | size_t dstHeightFull = AlignLo(dstHeight, 4); |
491 | 0 | size_t dstWidthFull = AlignLo(dstWidth, 4); |
492 | 0 | size_t noseW = Simd::Min<size_t>(5, dstWidth + 1); |
493 | 0 | size_t noseH = Simd::Min<size_t>(5, dstHeight + 1); |
494 | 0 | size_t startY = padY ? 4 : 0; |
495 | 0 | size_t startX = padX ? 4 : 0; |
496 | 0 | if (padY || padH) |
497 | 0 | { |
498 | 0 | if (dstHeight == dstHeightFull) |
499 | 0 | dstHeightFull -= 4; |
500 | 0 | if (dstWidth == dstWidthFull) |
501 | 0 | dstWidthFull -= 4; |
502 | 0 | if (padY) |
503 | 0 | src -= (srcWidth + 1) * (trans ? srcChannels : 1); |
504 | 0 | } |
505 | 0 | size_t tailW = dstWidth - dstWidthFull + (padW ? 0 : 1); |
506 | 0 | size_t tailH = dstHeight - dstHeightFull + (padH ? 0 : 1); |
507 | 0 | if (trans) |
508 | 0 | { |
509 | 0 | size_t row = 0, col = 0; |
510 | 0 | if (padY) |
511 | 0 | { |
512 | 0 | if (padX) |
513 | 0 | WinogradKernel2x2Block4x4SetInput1t(src, srcWidth, srcChannels, 1, noseH, 1, noseW, dst, dstStride), dst += srcChannels; |
514 | 0 | for (col = startX; col < dstWidthFull; col += 4) |
515 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + col * srcChannels, srcWidth, srcChannels, 1, noseH, 0, 5, dst, dstStride), dst += srcChannels; |
516 | 0 | if (col < dstWidth) |
517 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + col * srcChannels, srcWidth, srcChannels, 1, noseH, 0, tailW, dst, dstStride), dst += srcChannels; |
518 | 0 | } |
519 | 0 | for (row = startY; row < dstHeightFull; row += 4) |
520 | 0 | { |
521 | 0 | if (padX) |
522 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + row * srcWidth * srcChannels, srcWidth, srcChannels, 0, 5, 1, noseW, dst, dstStride), dst += srcChannels; |
523 | 0 | for (col = startX; col < dstWidthFull; col += 4) |
524 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, dst, dstStride), dst += srcChannels; |
525 | 0 | if (col < dstWidth) |
526 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, 0, 5, 0, tailW, dst, dstStride), dst += srcChannels; |
527 | 0 | } |
528 | 0 | if (row < dstHeight) |
529 | 0 | { |
530 | 0 | if (padX) |
531 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + row * srcWidth * srcChannels, srcWidth, srcChannels, 0, tailH, 1, noseW, dst, dstStride), dst += srcChannels; |
532 | 0 | for (col = startX; col < dstWidthFull; col += 4) |
533 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, 0, tailH, 0, 5, dst, dstStride), dst += srcChannels; |
534 | 0 | if (col < dstWidth) |
535 | 0 | WinogradKernel2x2Block4x4SetInput1t(src + (row * srcWidth + col) * srcChannels, srcWidth, srcChannels, 0, tailH, 0, tailW, dst, dstStride), dst += srcChannels; |
536 | 0 | } |
537 | 0 | } |
538 | 0 | else |
539 | 0 | { |
540 | 0 | for (size_t c = 0; c < srcChannels; ++c) |
541 | 0 | { |
542 | 0 | size_t row = 0, col = 0; |
543 | 0 | if (padY) |
544 | 0 | { |
545 | 0 | if (padX) |
546 | 0 | WinogradKernel2x2Block4x4SetInput1n(src, srcWidth, 1, noseH, 1, noseW, dst++, dstStride); |
547 | 0 | for (col = startX; col < dstWidthFull; col += 4) |
548 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + col, srcWidth, 1, noseH, 0, 5, dst++, dstStride); |
549 | 0 | if (col < dstWidth) |
550 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + col, srcWidth, 1, noseH, 0, tailW, dst++, dstStride); |
551 | 0 | } |
552 | 0 | for (row = startY; row < dstHeightFull; row += 4) |
553 | 0 | { |
554 | 0 | if (padX) |
555 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + row * srcWidth, srcWidth, 0, 5, 1, noseW, dst++, dstStride); |
556 | 0 | for (col = startX; col < dstWidthFull; col += 4) |
557 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + row * srcWidth + col, srcWidth, dst++, dstStride); |
558 | 0 | if (col < dstWidth) |
559 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + row * srcWidth + col, srcWidth, 0, 5, 0, tailW, dst++, dstStride); |
560 | 0 | } |
561 | 0 | if (row < dstHeight) |
562 | 0 | { |
563 | 0 | if (padX) |
564 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + row * srcWidth, srcWidth, 0, tailH, 1, noseW, dst++, dstStride); |
565 | 0 | for (col = startX; col < dstWidthFull; col += 4) |
566 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + row * srcWidth + col, srcWidth, 0, tailH, 0, 5, dst++, dstStride); |
567 | 0 | if (col < dstWidth) |
568 | 0 | WinogradKernel2x2Block4x4SetInput1n(src + row * srcWidth + col, srcWidth, 0, tailH, 0, tailW, dst++, dstStride); |
569 | 0 | } |
570 | 0 | src += srcWidth * srcHeight; |
571 | 0 | } |
572 | 0 | } |
573 | 0 | } |
574 | | |
575 | | //----------------------------------------------------------------------- |
576 | | |
577 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetOutput1(const float* src, size_t stride, float dst[4]) |
578 | 0 | { |
579 | 0 | float s[25]; |
580 | 0 | s[0] = src[0 * stride]; |
581 | 0 | s[1] = src[1 * stride]; |
582 | 0 | s[2] = src[2 * stride]; |
583 | 0 | s[3] = src[3 * stride]; |
584 | 0 | s[4] = src[4 * stride]; |
585 | 0 | s[5] = src[5 * stride]; |
586 | 0 | s[6] = src[6 * stride]; |
587 | 0 | s[7] = src[7 * stride]; |
588 | 0 | s[8] = src[8 * stride]; |
589 | 0 | s[9] = src[9 * stride]; |
590 | 0 | s[10] = src[10 * stride]; |
591 | 0 | s[11] = src[11 * stride]; |
592 | 0 | s[12] = src[12 * stride]; |
593 | 0 | s[13] = src[13 * stride]; |
594 | 0 | s[14] = src[14 * stride]; |
595 | 0 | s[15] = src[15 * stride]; |
596 | 0 | s[16] = src[16 * stride]; |
597 | 0 | s[17] = src[17 * stride]; |
598 | 0 | s[18] = src[18 * stride]; |
599 | 0 | s[19] = src[19 * stride]; |
600 | 0 | s[20] = src[20 * stride]; |
601 | 0 | s[21] = src[21 * stride]; |
602 | 0 | s[22] = src[22 * stride]; |
603 | 0 | s[23] = src[23 * stride]; |
604 | 0 | s[24] = src[24 * stride]; |
605 | |
|
606 | 0 | float t[20]; |
607 | 0 | t[0] = s[0] + s[5] + s[10] + s[15]; |
608 | 0 | t[1] = s[1] + s[6] + s[11] + s[16]; |
609 | 0 | t[2] = s[2] + s[7] + s[12] + s[17]; |
610 | 0 | t[3] = s[3] + s[8] + s[13] + s[18]; |
611 | 0 | t[4] = s[4] + s[9] + s[14] + s[19]; |
612 | 0 | t[5] = s[5] - s[10] + 2 * s[15]; |
613 | 0 | t[6] = s[6] - s[11] + 2 * s[16]; |
614 | 0 | t[7] = s[7] - s[12] + 2 * s[17]; |
615 | 0 | t[8] = s[8] - s[13] + 2 * s[18]; |
616 | 0 | t[9] = s[9] - s[14] + 2 * s[19]; |
617 | 0 | t[10] = s[5] + s[10] + 4 * s[15]; |
618 | 0 | t[11] = s[6] + s[11] + 4 * s[16]; |
619 | 0 | t[12] = s[7] + s[12] + 4 * s[17]; |
620 | 0 | t[13] = s[8] + s[13] + 4 * s[18]; |
621 | 0 | t[14] = s[9] + s[14] + 4 * s[19]; |
622 | 0 | t[15] = s[5] - s[10] + 8 * s[15] + s[20]; |
623 | 0 | t[16] = s[6] - s[11] + 8 * s[16] + s[21]; |
624 | 0 | t[17] = s[7] - s[12] + 8 * s[17] + s[22]; |
625 | 0 | t[18] = s[8] - s[13] + 8 * s[18] + s[23]; |
626 | 0 | t[19] = s[9] - s[14] + 8 * s[19] + s[24]; |
627 | |
|
628 | 0 | dst[0] = t[0] + t[1] + t[2] + t[3]; |
629 | 0 | dst[1] = t[1] - t[2] + 2 * t[3]; |
630 | 0 | dst[2] = t[1] + t[2] + 4 * t[3]; |
631 | 0 | dst[3] = t[1] - t[2] + 8 * t[3] + t[4]; |
632 | 0 | dst[4] = t[5] + t[6] + t[7] + t[8]; |
633 | 0 | dst[5] = t[6] - t[7] + 2 * t[8]; |
634 | 0 | dst[6] = t[6] + t[7] + 4 * t[8]; |
635 | 0 | dst[7] = t[6] - t[7] + 8 * t[8] + t[9]; |
636 | 0 | dst[8] = t[10] + t[11] + t[12] + t[13]; |
637 | 0 | dst[9] = t[11] - t[12] + 2 * t[13]; |
638 | 0 | dst[10] = t[11] + t[12] + 4 * t[13]; |
639 | 0 | dst[11] = t[11] - t[12] + 8 * t[13] + t[14]; |
640 | 0 | dst[12] = t[15] + t[16] + t[17] + t[18]; |
641 | 0 | dst[13] = t[16] - t[17] + 2 * t[18]; |
642 | 0 | dst[14] = t[16] + t[17] + 4 * t[18]; |
643 | 0 | dst[15] = t[16] - t[17] + 8 * t[18] + t[19]; |
644 | 0 | } |
645 | | |
646 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetOutput1n(const float* src, size_t srcStride, float* dst, size_t dstStride) |
647 | 0 | { |
648 | 0 | float tmp[16]; |
649 | 0 | WinogradKernel2x2Block4x4SetOutput1(src, srcStride, tmp); |
650 | 0 | dst[0 * dstStride + 0] = tmp[0]; |
651 | 0 | dst[0 * dstStride + 1] = tmp[1]; |
652 | 0 | dst[0 * dstStride + 2] = tmp[2]; |
653 | 0 | dst[0 * dstStride + 3] = tmp[3]; |
654 | 0 | dst[1 * dstStride + 0] = tmp[4]; |
655 | 0 | dst[1 * dstStride + 1] = tmp[5]; |
656 | 0 | dst[1 * dstStride + 2] = tmp[6]; |
657 | 0 | dst[1 * dstStride + 3] = tmp[7]; |
658 | 0 | dst[2 * dstStride + 0] = tmp[8]; |
659 | 0 | dst[2 * dstStride + 1] = tmp[9]; |
660 | 0 | dst[2 * dstStride + 2] = tmp[10]; |
661 | 0 | dst[2 * dstStride + 3] = tmp[11]; |
662 | 0 | dst[3 * dstStride + 0] = tmp[12]; |
663 | 0 | dst[3 * dstStride + 1] = tmp[13]; |
664 | 0 | dst[3 * dstStride + 2] = tmp[14]; |
665 | 0 | dst[3 * dstStride + 3] = tmp[15]; |
666 | 0 | } |
667 | | |
668 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetOutput1n(const float* src, size_t srcStride, float* dst, size_t dstStride, size_t rowE, size_t colE) |
669 | 0 | { |
670 | 0 | float tmp[16]; |
671 | 0 | WinogradKernel2x2Block4x4SetOutput1(src, srcStride, tmp); |
672 | 0 | for (size_t row = 0; row < rowE; ++row) |
673 | 0 | for (size_t col = 0; col < colE; ++col) |
674 | 0 | dst[row * dstStride + col] = tmp[row * 4 + col]; |
675 | 0 | } |
676 | | |
677 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetOutput1t(const float* src, size_t srcStride, float* dst, size_t dstW, size_t dstC) |
678 | 0 | { |
679 | 0 | size_t dstS = dstW * dstC; |
680 | 0 | for (size_t d = 0; d < dstC; ++d, src++, dst++) |
681 | 0 | { |
682 | 0 | float tmp[16]; |
683 | 0 | WinogradKernel2x2Block4x4SetOutput1(src, srcStride, tmp); |
684 | 0 | dst[0 * dstS + 0 * dstC] = tmp[0]; |
685 | 0 | dst[0 * dstS + 1 * dstC] = tmp[1]; |
686 | 0 | dst[0 * dstS + 2 * dstC] = tmp[2]; |
687 | 0 | dst[0 * dstS + 3 * dstC] = tmp[3]; |
688 | 0 | dst[1 * dstS + 0 * dstC] = tmp[4]; |
689 | 0 | dst[1 * dstS + 1 * dstC] = tmp[5]; |
690 | 0 | dst[1 * dstS + 2 * dstC] = tmp[6]; |
691 | 0 | dst[1 * dstS + 3 * dstC] = tmp[7]; |
692 | 0 | dst[2 * dstS + 0 * dstC] = tmp[8]; |
693 | 0 | dst[2 * dstS + 1 * dstC] = tmp[9]; |
694 | 0 | dst[2 * dstS + 2 * dstC] = tmp[10]; |
695 | 0 | dst[2 * dstS + 3 * dstC] = tmp[11]; |
696 | 0 | dst[3 * dstS + 0 * dstC] = tmp[12]; |
697 | 0 | dst[3 * dstS + 1 * dstC] = tmp[13]; |
698 | 0 | dst[3 * dstS + 2 * dstC] = tmp[14]; |
699 | 0 | dst[3 * dstS + 3 * dstC] = tmp[15]; |
700 | 0 | } |
701 | 0 | } |
702 | | |
703 | | SIMD_INLINE void WinogradKernel2x2Block4x4SetOutput1t(const float* src, size_t srcStride, float* dst, size_t dstW, size_t dstC, size_t rowE, size_t colE) |
704 | 0 | { |
705 | 0 | size_t dstS = dstW * dstC; |
706 | 0 | for (size_t d = 0; d < dstC; ++d, src++, dst++) |
707 | 0 | { |
708 | 0 | float tmp[16]; |
709 | 0 | WinogradKernel2x2Block4x4SetOutput1(src, srcStride, tmp); |
710 | 0 | for (size_t row = 0; row < rowE; ++row) |
711 | 0 | for (size_t col = 0; col < colE; ++col) |
712 | 0 | dst[row * dstS + col * dstC] = tmp[row * 4 + col]; |
713 | 0 | } |
714 | 0 | } |
715 | | |
716 | | void WinogradKernel2x2Block4x4SetOutput(const float* src, size_t srcStride, float* dst, size_t dstChannels, size_t dstHeight, size_t dstWidth, SimdBool trans) |
717 | 0 | { |
718 | 0 | size_t dstHeightFull = AlignLo(dstHeight, 4); |
719 | 0 | size_t dstWidthFull = AlignLo(dstWidth, 4); |
720 | 0 | if (trans) |
721 | 0 | { |
722 | 0 | size_t row, col; |
723 | 0 | for (row = 0; row < dstHeightFull; row += 4) |
724 | 0 | { |
725 | 0 | for (col = 0; col < dstWidthFull; col += 4) |
726 | 0 | WinogradKernel2x2Block4x4SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels), src += dstChannels; |
727 | 0 | if (col < dstWidth) |
728 | 0 | WinogradKernel2x2Block4x4SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels, 4, dstWidth - col), src += dstChannels; |
729 | 0 | } |
730 | 0 | if (row < dstHeight) |
731 | 0 | { |
732 | 0 | for (col = 0; col < dstWidthFull; col += 4) |
733 | 0 | WinogradKernel2x2Block4x4SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels, dstHeight - row, 4), src += dstChannels; |
734 | 0 | if (col < dstWidth) |
735 | 0 | WinogradKernel2x2Block4x4SetOutput1t(src, srcStride, dst + (row * dstWidth + col) * dstChannels, dstWidth, dstChannels, dstHeight - row, dstWidth - col), src += dstChannels; |
736 | 0 | } |
737 | 0 | } |
738 | 0 | else |
739 | 0 | { |
740 | 0 | for (size_t c = 0; c < dstChannels; ++c) |
741 | 0 | { |
742 | 0 | size_t row, col; |
743 | 0 | for (row = 0; row < dstHeightFull; row += 4) |
744 | 0 | { |
745 | 0 | for (col = 0; col < dstWidthFull; col += 4) |
746 | 0 | WinogradKernel2x2Block4x4SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth); |
747 | 0 | if (col < dstWidth) |
748 | 0 | WinogradKernel2x2Block4x4SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth, 4, dstWidth - col); |
749 | 0 | } |
750 | 0 | if (row < dstHeight) |
751 | 0 | { |
752 | 0 | for (col = 0; col < dstWidthFull; col += 4) |
753 | 0 | WinogradKernel2x2Block4x4SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth, dstHeight - row, 4); |
754 | 0 | if (col < dstWidth) |
755 | 0 | WinogradKernel2x2Block4x4SetOutput1n(src++, srcStride, dst + row * dstWidth + col, dstWidth, dstHeight - row, dstWidth - col); |
756 | 0 | } |
757 | 0 | dst += dstHeight * dstWidth; |
758 | 0 | } |
759 | 0 | } |
760 | 0 | } |
761 | | } |
762 | | #endif |
763 | | } |