Expression Templates Library (ETL)
avg_pooling_upsample.hpp
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
8 #pragma once
9 
10 #include "etl/concepts.hpp"
11 namespace etl::impl::standard {
12 
26  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, typename C, typename M>
27  static void pool_block_2d(const C& errors, M& m, size_t i, size_t j) {
28  auto error = errors(i, j);
29 
30  // Slow path for cells with padding
31  if constexpr (P1 || P2) {
32  if (cpp_unlikely(i < P1 || j < P2 || i >= etl::dim<0>(errors) - P1 || j >= etl::dim<1>(errors) - P2)) {
33  const size_t base_i = i * S1 - P1;
34  const size_t base_j = j * S2 - P2;
35 
36  for (size_t ii = 0; ii < C1; ++ii) {
37  for (size_t jj = 0; jj < C2; ++jj) {
38  if (base_i + ii < etl::dim<0>(m) && base_j + jj < etl::dim<1>(m)) {
39  if constexpr (S1 == C1 && S2 == C2) {
40  m(base_i + ii, base_j + jj) = error / value_t<M>(C1 * C2);
41  } else {
42  m(base_i + ii, base_j + jj) += error / value_t<M>(C1 * C2);
43  }
44  }
45  }
46  }
47 
48  return;
49  }
50  }
51 
52  if constexpr (S1 == C1 && S2 == C2) {
53  for (size_t ii = 0; ii < C1; ++ii) {
54  for (size_t jj = 0; jj < C2; ++jj) {
55  m(i * S1 - P1 + ii, j * S2 - P2 + jj) = error / value_t<M>(C1 * C2);
56  }
57  }
58  } else {
59  for (size_t ii = 0; ii < C1; ++ii) {
60  for (size_t jj = 0; jj < C2; ++jj) {
61  m(i * S1 - P1 + ii, j * S2 - P2 + jj) += error / value_t<M>(C1 * C2);
62  }
63  }
64  }
65  }
66 
76  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, typename C, typename M>
77  static void pool_block_3d(const C& errors, M& m, size_t q, size_t i, size_t j) {
78  auto error = errors(q, i, j);
79 
80  // Slow path for cells with padding
81  if constexpr (P1 || P2) {
82  if (cpp_unlikely(i < P1 || j < P2 || i >= etl::dim<1>(errors) - P1 || j >= etl::dim<2>(errors) - P2)) {
83  const size_t base_i = i * S1 - P1;
84  const size_t base_j = j * S2 - P2;
85 
86  for (size_t ii = 0; ii < C1; ++ii) {
87  for (size_t jj = 0; jj < C2; ++jj) {
88  if (base_i + ii < etl::dim<1>(m) && base_j + jj < etl::dim<2>(m)) {
89  if constexpr (S1 == C1 && S2 == C2) {
90  m(q, base_i + ii, base_j + jj) = error / value_t<M>(C1 * C2);
91  } else {
92  m(q, base_i + ii, base_j + jj) += error / value_t<M>(C1 * C2);
93  }
94  }
95  }
96  }
97 
98  return;
99  }
100  }
101 
102  if constexpr (S1 == C1 && S2 == C2) {
103  for (size_t ii = 0; ii < C1; ++ii) {
104  for (size_t jj = 0; jj < C2; ++jj) {
105  m(q, i * S1 - P1 + ii, j * S2 - P2 + jj) = error / value_t<M>(C1 * C2);
106  }
107  }
108  } else {
109  for (size_t ii = 0; ii < C1; ++ii) {
110  for (size_t jj = 0; jj < C2; ++jj) {
111  m(q, i * S1 - P1 + ii, j * S2 - P2 + jj) += error / (C1 * C2);
112  }
113  }
114  }
115  }
116 
126  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, typename C, typename M>
127  static void pool_block_4d(const C& errors, M& m, size_t p, size_t q, size_t i, size_t j) {
128  auto error = errors(p, q, i, j);
129 
130  // Slow path for cells with padding
131  if constexpr (P1 || P2) {
132  if (cpp_unlikely(i < P1 || j < P2 || i >= etl::dim<2>(errors) - P1 || j >= etl::dim<3>(errors) - P2)) {
133  const size_t base_i = i * S1 - P1;
134  const size_t base_j = j * S2 - P2;
135 
136  for (size_t ii = 0; ii < C1; ++ii) {
137  for (size_t jj = 0; jj < C2; ++jj) {
138  if (base_i + ii < etl::dim<2>(m) && base_j + jj < etl::dim<3>(m)) {
139  if constexpr (S1 == C1 && S2 == C2) {
140  m(p, q, base_i + ii, base_j + jj) = error / value_t<M>(C1 * C2);
141  } else {
142  m(p, q, base_i + ii, base_j + jj) += error / value_t<M>(C1 * C2);
143  }
144  }
145  }
146  }
147 
148  return;
149  }
150  }
151 
152  if constexpr (S1 == C1 && S2 == C2) {
153  for (size_t ii = 0; ii < C1; ++ii) {
154  for (size_t jj = 0; jj < C2; ++jj) {
155  m(p, q, i * S1 - P1 + ii, j * S2 - P2 + jj) = error / value_t<M>(C1 * C2);
156  }
157  }
158  } else {
159  for (size_t ii = 0; ii < C1; ++ii) {
160  for (size_t jj = 0; jj < C2; ++jj) {
161  m(p, q, i * S1 - P1 + ii, j * S2 - P2 + jj) += error / value_t<M>(C1 * C2);
162  }
163  }
164  }
165  }
166 
176  template <typename C, typename M>
177  static void pool_block_2d(const C& errors, M& m, size_t i, size_t j, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
178  auto error = errors(i, j);
179 
180  // Slow path for cells with padding
181  if (cpp_unlikely(p1 || p2)) {
182  if (cpp_unlikely(i < p1 || j < p2 || i >= etl::dim<0>(errors) - p1 || j >= etl::dim<1>(errors) - p2)) {
183  const size_t base_i = i * s1 - p1;
184  const size_t base_j = j * s2 - p2;
185 
186  for (size_t ii = 0; ii < c1; ++ii) {
187  for (size_t jj = 0; jj < c2; ++jj) {
188  if (base_i + ii < etl::dim<0>(m) && base_j + jj < etl::dim<1>(m)) {
189  if (s1 == c1 && s2 == c2) {
190  m(base_i + ii, base_j + jj) = error / value_t<M>(c1 * c2);
191  } else {
192  m(base_i + ii, base_j + jj) += error / value_t<M>(c1 * c2);
193  }
194  }
195  }
196  }
197 
198  return;
199  }
200  }
201 
202  if (s1 == c1 && s2 == c2) {
203  for (size_t ii = 0; ii < c1; ++ii) {
204  for (size_t jj = 0; jj < c2; ++jj) {
205  m(i * s1 - p1 + ii, j * s2 - p2 + jj) = error / value_t<M>(c1 * c2);
206  }
207  }
208  } else {
209  for (size_t ii = 0; ii < c1; ++ii) {
210  for (size_t jj = 0; jj < c2; ++jj) {
211  m(i * s1 - p1 + ii, j * s2 - p2 + jj) += error / value_t<M>(c1 * c2);
212  }
213  }
214  }
215  }
216 
226  template <typename C, typename M>
227  static void pool_block_3d(const C& errors, M& m, size_t q, size_t i, size_t j, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
228  auto error = errors(q, i, j);
229 
230  // Slow path for cells with padding
231  if (cpp_unlikely(p1 || p2)) {
232  if (cpp_unlikely(i < p1 || j < p2 || i >= etl::dim<1>(errors) - p1 || j >= etl::dim<2>(errors) - p2)) {
233  const size_t base_i = i * s1 - p1;
234  const size_t base_j = j * s2 - p2;
235 
236  for (size_t ii = 0; ii < c1; ++ii) {
237  for (size_t jj = 0; jj < c2; ++jj) {
238  if (base_i + ii < etl::dim<1>(m) && base_j + jj < etl::dim<2>(m)) {
239  if (s1 == c1 && s2 == c2) {
240  m(q, base_i + ii, base_j + jj) = error / value_t<M>(c1 * c2);
241  } else {
242  m(q, base_i + ii, base_j + jj) += error / value_t<M>(c1 * c2);
243  }
244  }
245  }
246  }
247 
248  return;
249  }
250  }
251 
252  if (s1 == c1 && s2 == c2) {
253  for (size_t ii = 0; ii < c1; ++ii) {
254  for (size_t jj = 0; jj < c2; ++jj) {
255  m(q, i * s1 - p1 + ii, j * s2 - p2 + jj) = error / value_t<M>(c1 * c2);
256  }
257  }
258  } else {
259  for (size_t ii = 0; ii < c1; ++ii) {
260  for (size_t jj = 0; jj < c2; ++jj) {
261  m(q, i * s1 - p1 + ii, j * s2 - p2 + jj) += error / value_t<M>(c1 * c2);
262  }
263  }
264  }
265  }
266 
276  template <typename C, typename M>
277  static void pool_block_4d(const C& errors, M& m, size_t p, size_t q, size_t i, size_t j, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
278  auto error = errors(p, q, i, j);
279 
280  // Slow path for cells with padding
281  if (cpp_unlikely(p1 || p2)) {
282  if (cpp_unlikely(i < p1 || j < p2 || i >= etl::dim<2>(errors) - p1 || j >= etl::dim<3>(errors) - p2)) {
283  const size_t base_i = i * s1 - p1;
284  const size_t base_j = j * s2 - p2;
285 
286  for (size_t ii = 0; ii < c1; ++ii) {
287  for (size_t jj = 0; jj < c2; ++jj) {
288  if (base_i + ii < etl::dim<2>(m) && base_j + jj < etl::dim<3>(m)) {
289  if (s1 == c1 && s2 == c2) {
290  m(p, q, base_i + ii, base_j + jj) = error / value_t<M>(c1 * c2);
291  } else {
292  m(p, q, base_i + ii, base_j + jj) += error / value_t<M>(c1 * c2);
293  }
294  }
295  }
296  }
297 
298  return;
299  }
300  }
301 
302  if (s1 == c1 && s2 == c2) {
303  for (size_t ii = 0; ii < c1; ++ii) {
304  for (size_t jj = 0; jj < c2; ++jj) {
305  m(p, q, i * s1 - p1 + ii, j * s2 - p2 + jj) = error / value_t<M>(c1 * c2);
306  }
307  }
308  } else {
309  for (size_t ii = 0; ii < c1; ++ii) {
310  for (size_t jj = 0; jj < c2; ++jj) {
311  m(p, q, i * s1 - p1 + ii, j * s2 - p2 + jj) += error / value_t<M>(c1 * c2);
312  }
313  }
314  }
315  }
316 
317  // 2D Handling
318 
326  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, etl_2d A, typename B, typename C, typename M>
327  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m) {
328  if constexpr (S1 != C1 || S2 != C2) {
329  m = 0;
330  }
331 
332  for (size_t i = 0; i < etl::dim<0>(out); ++i) {
333  for (size_t j = 0; j < etl::dim<1>(out); ++j) {
334  pool_block_2d<C1, C2, S1, S2, P1, P2>(errors, m, i, j);
335  }
336  }
337  }
338 
346  template <etl_2d A, typename B, typename C, typename M>
347  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
348  if (s1 != c1 || s2 != c2) {
349  m = 0;
350  }
351 
352  for (size_t i = 0; i < etl::dim<0>(out); ++i) {
353  for (size_t j = 0; j < etl::dim<1>(out); ++j) {
354  pool_block_2d(errors, m, i, j, c1, c2, s1, s2, p1, p2);
355  }
356  }
357  }
358 
359  // 3D Handling
360 
368  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, etl_3d A, typename B, typename C, typename M>
369  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m) {
370  if constexpr (S1 != C1 || S2 != C2) {
371  m = 0;
372  }
373 
374  auto batch_fun = [&](const size_t first, const size_t last) {
375  for (size_t q = first; q < last; ++q) {
376  for (size_t i = 0; i < etl::dim<1>(out); ++i) {
377  for (size_t j = 0; j < etl::dim<2>(out); ++j) {
378  pool_block_3d<C1, C2, S1, S2, P1, P2>(errors, m, q, i, j);
379  }
380  }
381  }
382  };
383 
384  const size_t N = etl::dim<0>(out);
385 
386  engine_dispatch_1d_serial(batch_fun, 0, N, 2UL);
387  }
388 
396  template <etl_3d A, typename B, typename C, typename M>
397  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
398  if (s1 != c1 || s2 != c2) {
399  m = 0;
400  }
401 
402  auto batch_fun = [&](const size_t first, const size_t last) {
403  for (size_t q = first; q < last; ++q) {
404  for (size_t i = 0; i < etl::dim<1>(out); ++i) {
405  for (size_t j = 0; j < etl::dim<2>(out); ++j) {
406  pool_block_3d(errors, m, q, i, j, c1, c2, s1, s2, p1, p2);
407  }
408  }
409  }
410  };
411 
412  const size_t N = etl::dim<0>(out);
413 
414  engine_dispatch_1d_serial(batch_fun, 0, N, 2UL);
415  }
416 
417  // 4D Handling
418 
426  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, etl_4d A, typename B, typename C, typename M>
427  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m) {
428  if constexpr (S1 != C1 || S2 != C2) {
429  m = 0;
430  }
431 
432  auto batch_fun = [&](const size_t first, const size_t last) {
433  for (size_t p = first; p < last; ++p) {
434  for (size_t q = 0; q < etl::dim<1>(out); ++q) {
435  for (size_t i = 0; i < etl::dim<2>(out); ++i) {
436  for (size_t j = 0; j < etl::dim<3>(out); ++j) {
437  pool_block_4d<C1, C2, S1, S2, P1, P2>(errors, m, p, q, i, j);
438  }
439  }
440  }
441  }
442  };
443 
444  const size_t N = etl::dim<0>(out);
445 
446  engine_dispatch_1d_serial(batch_fun, 0, N, 2UL);
447  }
448 
456  template <etl_4d A, typename B, typename C, typename M>
457  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
458  if (s1 != c1 || s2 != c2) {
459  m = 0;
460  }
461 
462  auto batch_fun = [&](const size_t first, const size_t last) {
463  for (size_t p = first; p < last; ++p) {
464  for (size_t q = 0; q < etl::dim<1>(out); ++q) {
465  for (size_t i = 0; i < etl::dim<2>(out); ++i) {
466  for (size_t j = 0; j < etl::dim<3>(out); ++j) {
467  pool_block_4d(errors, m, p, q, i, j, c1, c2, s1, s2, p1, p2);
468  }
469  }
470  }
471  }
472  };
473 
474  const size_t N = etl::dim<0>(out);
475 
476  engine_dispatch_1d_serial(batch_fun, 0, N, 2UL);
477  }
478 
479  // Deep handling
480 
488  template <size_t C1, size_t C2, size_t S1, size_t S2, size_t P1, size_t P2, etl_5d_and_plus A, typename B, typename C, typename M>
489  static void apply(A&& in, B&& out, C&& errors, M& m) {
490  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
491  apply<C1, C2, S1, S2, P1, P2>(in(i), out(i), errors(i), m(i));
492  }
493  }
494 
502  template <etl_5d_and_plus A, typename B, typename C, typename M>
503  static void apply(A&& in, B&& out, C&& errors, M& m, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2) {
504  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
505  apply(in(i), out(i), errors(i), m(i), c1, c2, s1, s2, p1, p2);
506  }
507  }
508 };
509 
525  template <size_t C1, size_t C2, size_t C3, typename C, typename M>
526  static void pool_block_3d(const C& errors, M& m, size_t i, size_t j, size_t k) {
527  auto error = errors(i, j, k);
528 
529  for (size_t ii = 0; ii < C1; ++ii) {
530  for (size_t jj = 0; jj < C2; ++jj) {
531  for (size_t kk = 0; kk < C3; ++kk) {
532  m(i * C1 + ii, j * C2 + jj, k * C3 + kk) = error / value_t<M>(C1 * C2 * C3);
533  }
534  }
535  }
536  }
537 
549  template <size_t C1, size_t C2, size_t C3, typename C, typename M>
550  static void pool_block_4d(const C& errors, M& m, size_t n, size_t i, size_t j, size_t k) {
551  auto error = errors(n, i, j, k);
552 
553  for (size_t ii = 0; ii < C1; ++ii) {
554  for (size_t jj = 0; jj < C2; ++jj) {
555  for (size_t kk = 0; kk < C3; ++kk) {
556  m(n, i * C1 + ii, j * C2 + jj, k * C3 + kk) = error / value_t<M>(C1 * C2 * C3);
557  }
558  }
559  }
560  }
561 
573  template <typename C, typename M>
574  static void pool_block_3d(const C& errors, M& m, size_t i, size_t j, size_t k, size_t c1, size_t c2, size_t c3) {
575  auto error = errors(i, j, k);
576 
577  for (size_t ii = 0; ii < c1; ++ii) {
578  for (size_t jj = 0; jj < c2; ++jj) {
579  for (size_t kk = 0; kk < c3; ++kk) {
580  m(i * c1 + ii, j * c2 + jj, k * c3 + kk) = error / value_t<M>(c1 * c2 * c3);
581  }
582  }
583  }
584  }
585 
597  template <typename C, typename M>
598  static void pool_block_4d(const C& errors, M& m, size_t n, size_t i, size_t j, size_t k, size_t c1, size_t c2, size_t c3) {
599  auto error = errors(n, i, j, k);
600 
601  for (size_t ii = 0; ii < c1; ++ii) {
602  for (size_t jj = 0; jj < c2; ++jj) {
603  for (size_t kk = 0; kk < c3; ++kk) {
604  m(n, i * c1 + ii, j * c2 + jj, k * c3 + kk) = error / value_t<M>(c1 * c2 * c3);
605  }
606  }
607  }
608  }
609 
618  template <size_t C1, size_t C2, size_t C3, etl_3d A, typename B, typename C, typename M>
619  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m) {
620  for (size_t i = 0; i < etl::dim<0>(out); ++i) {
621  for (size_t j = 0; j < etl::dim<1>(out); ++j) {
622  for (size_t k = 0; k < etl::dim<2>(out); ++k) {
623  pool_block_3d<C1, C2, C3>(errors, m, i, j, k);
624  }
625  }
626  }
627  }
628 
637  template <etl_3d A, typename B, typename C, typename M>
638  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M&& m, size_t c1, size_t c2, size_t c3) {
639  for (size_t i = 0; i < etl::dim<0>(out); ++i) {
640  for (size_t j = 0; j < etl::dim<1>(out); ++j) {
641  for (size_t k = 0; k < etl::dim<2>(out); ++k) {
642  pool_block_3d(errors, m, i, j, k, c1, c2, c3);
643  }
644  }
645  }
646  }
647 
648  /*
649  * 4D handling
650  *
651  * This is especially optimized because this is the most common
652  * case in machine learning. Moreover, this is also easy to
653  * parallelize and optimize
654  */
655 
664  template <size_t C1, size_t C2, size_t C3, etl_4d A, typename B, typename C, typename M>
665  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M& m) {
666  auto batch_fun_n = [&](const size_t first, const size_t last) {
667  for (size_t n = first; n < last; ++n) {
668  for (size_t i = 0; i < etl::dim<1>(out); ++i) {
669  for (size_t j = 0; j < etl::dim<2>(out); ++j) {
670  for (size_t k = 0; k < etl::dim<3>(out); ++k) {
671  avg_pool_upsample_3d::pool_block_4d<C1, C2, C3>(errors, m, n, i, j, k);
672  }
673  }
674  }
675  }
676  };
677 
678  const size_t N = etl::dim<0>(out);
679 
680  engine_dispatch_1d_serial(batch_fun_n, 0, N, 2UL);
681  }
682 
691  template <etl_4d A, typename B, typename C, typename M>
692  static void apply([[maybe_unused]] A&& in, [[maybe_unused]] B&& out, C&& errors, M& m, size_t c1, size_t c2, size_t c3) {
693  auto batch_fun_n = [&](const size_t first, const size_t last) {
694  for (size_t n = first; n < last; ++n) {
695  for (size_t i = 0; i < etl::dim<1>(out); ++i) {
696  for (size_t j = 0; j < etl::dim<2>(out); ++j) {
697  for (size_t k = 0; k < etl::dim<3>(out); ++k) {
698  avg_pool_upsample_3d::pool_block_4d(errors, m, n, i, j, k, c1, c2, c3);
699  }
700  }
701  }
702  }
703  };
704 
705  const size_t N = etl::dim<0>(out);
706 
707  engine_dispatch_1d_serial(batch_fun_n, 0, N, 2UL);
708  }
709 
710  // Deep handling
711 
720  template <size_t C1, size_t C2, size_t C3, etl_5d_and_plus A, typename B, typename C, typename M>
721  static void apply(A&& in, B&& out, C&& errors, M& m) {
722  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
723  apply<C1, C2, C3>(in(i), out(i), errors(i), m(i));
724  }
725  }
726 
735  template <etl_5d_and_plus A, typename B, typename C, typename M>
736  static void apply(A&& in, B&& out, C&& errors, M& m, size_t c1, size_t c2, size_t c3) {
737  for (size_t i = 0; i < etl::dim<0>(in); ++i) {
738  apply(in(i), out(i), errors(i), m(i), c1, c2, c3);
739  }
740  }
741 };
742 
743 } //end of namespace etl::impl::standard
static void apply([[maybe_unused]] A &&in, [[maybe_unused]] B &&out, C &&errors, M &&m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:619
static void apply(A &&in, B &&out, C &&errors, M &m, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:503
static void apply(A &&in, B &&out, C &&errors, M &m, size_t c1, size_t c2, size_t c3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:736
static void pool_block_3d(const C &errors, M &m, size_t i, size_t j, size_t k)
Pool a 3D block of the sub expression.
Definition: avg_pooling_upsample.hpp:526
void engine_dispatch_1d_serial(Functor &&functor, size_t first, size_t last, size_t threshold, [[maybe_unused]] size_t n_threads=etl::threads)
Dispatch the elements of a range to a functor in a parallel manner, using the global thread engine...
Definition: parallel_support.hpp:734
static void apply([[maybe_unused]] A &&in, [[maybe_unused]] B &&out, C &&errors, M &&m, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:347
static void pool_block_4d(const C &errors, M &m, size_t p, size_t q, size_t i, size_t j)
Pool a block of the sub expression.
Definition: avg_pooling_upsample.hpp:127
Functor for the derivative of 3D Avg Pooling.
Definition: avg_pooling_upsample.hpp:513
static void apply(A &&in, B &&out, C &&errors, M &m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:721
Definition: prob_pooling.hpp:10
static void pool_block_4d(const C &errors, M &m, size_t p, size_t q, size_t i, size_t j, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2)
Pool a block of the sub expression.
Definition: avg_pooling_upsample.hpp:277
static void pool_block_3d(const C &errors, M &m, size_t q, size_t i, size_t j)
Pool a block of the sub expression.
Definition: avg_pooling_upsample.hpp:77
static void apply([[maybe_unused]] A &&in, [[maybe_unused]] B &&out, C &&errors, M &m, size_t c1, size_t c2, size_t c3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:692
static void pool_block_4d(const C &errors, M &m, size_t n, size_t i, size_t j, size_t k, size_t c1, size_t c2, size_t c3)
Pool a 4D block of the sub expression.
Definition: avg_pooling_upsample.hpp:598
static void pool_block_2d(const C &errors, M &m, size_t i, size_t j)
Pool a block of the sub expression.
Definition: avg_pooling_upsample.hpp:27
static void pool_block_4d(const C &errors, M &m, size_t n, size_t i, size_t j, size_t k)
Pool a 4D block of the sub expression.
Definition: avg_pooling_upsample.hpp:550
static void pool_block_2d(const C &errors, M &m, size_t i, size_t j, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2)
Pool a block of the sub expression.
Definition: avg_pooling_upsample.hpp:177
static void apply([[maybe_unused]] A &&in, [[maybe_unused]] B &&out, C &&errors, M &m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:665
Functor for the derivative of 2D Max Pooling.
Definition: avg_pooling_upsample.hpp:16
static void pool_block_3d(const C &errors, M &m, size_t q, size_t i, size_t j, size_t c1, size_t c2, size_t s1, size_t s2, size_t p1, size_t p2)
Pool a block of the sub expression.
Definition: avg_pooling_upsample.hpp:227
static void apply([[maybe_unused]] A &&in, [[maybe_unused]] B &&out, C &&errors, M &&m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:327
static void apply(A &&in, B &&out, C &&errors, M &m)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:489
typename decay_traits< E >::value_type value_t
Traits to extract the value type out of an ETL type.
Definition: tmp.hpp:81
static void apply([[maybe_unused]] A &&in, [[maybe_unused]] B &&out, C &&errors, M &&m, size_t c1, size_t c2, size_t c3)
Apply the functor on sub and store the result in m.
Definition: avg_pooling_upsample.hpp:638
static void pool_block_3d(const C &errors, M &m, size_t i, size_t j, size_t k, size_t c1, size_t c2, size_t c3)
Pool a 3D block of the sub expression.
Definition: avg_pooling_upsample.hpp:574