• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/core/kernels/eigen_pooling.h"
17 #include "tensorflow/core/platform/test.h"
18 
19 namespace Eigen {
20 
21 namespace {
EigenApprox(float a,float b)22 void EigenApprox(float a, float b) {
23   ASSERT_TRUE(std::abs(a - b) <= std::min(std::abs(a), std::abs(b)) * 1e-3);
24 }
25 }  // namespace
26 
TEST(EigenPoolingTest,Simple)27 TEST(EigenPoolingTest, Simple) {
28   const int depth = 10;
29   const int input_rows = 5;
30   const int input_cols = 5;
31   const int num_batches = 13;
32   const int patch_rows = 4;
33   const int patch_cols = 4;
34   const int output_rows = 2;
35   const int output_cols = 2;
36 
37   Tensor<float, 4> input(depth, input_rows, input_cols, num_batches);
38   Tensor<float, 4> result(depth, output_rows, output_cols, num_batches);
39   input = input.constant(11.0f) + input.random();
40   result.setRandom();
41   result = result.constant(-1000.f);
42 
43   // Max pooling using a 4x4 window and a stride of 1.
44   const int stride = 1;
45   result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
46                              PADDING_VALID);
47 
48   EXPECT_EQ(result.dimension(0), depth);
49   EXPECT_EQ(result.dimension(1), output_rows);
50   EXPECT_EQ(result.dimension(2), output_cols);
51   EXPECT_EQ(result.dimension(3), num_batches);
52 
53   for (int b = 0; b < num_batches; ++b) {
54     for (int d = 0; d < depth; ++d) {
55       for (int i = 0; i < output_rows; ++i) {
56         for (int j = 0; j < output_cols; ++j) {
57           float expected = -10000.f;
58           for (int r = 0; r < patch_rows; ++r) {
59             for (int c = 0; c < patch_cols; ++c) {
60               expected = (std::max)(expected, input(d, r + i, c + j, b));
61             }
62           }
63           if (result(d, i, j, b) != expected) {
64             std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
65                       << " " << result(d, i, j, b) << " vs " << expected
66                       << std::endl;
67           }
68           EigenApprox(result(d, i, j, b), expected);
69         }
70       }
71     }
72   }
73 }
74 
TEST(EigenPoolingTest,SimpleRowMajor)75 TEST(EigenPoolingTest, SimpleRowMajor) {
76   const int depth = 10;
77   const int input_rows = 5;
78   const int input_cols = 5;
79   const int num_batches = 13;
80   const int patch_rows = 4;
81   const int patch_cols = 4;
82   const int output_rows = 2;
83   const int output_cols = 2;
84 
85   Tensor<float, 4, RowMajor> input(num_batches, input_cols, input_rows, depth);
86   Tensor<float, 4, RowMajor> result(num_batches, output_cols, output_rows,
87                                     depth);
88   input = input.constant(11.0f) + input.random();
89   result.setRandom();
90   result = result.constant(-1000.f);
91 
92   // Max pooling using a 4x4 window and a stride of 1.
93   const int stride = 1;
94   result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
95                              PADDING_VALID);
96 
97   EXPECT_EQ(result.dimension(3), depth);
98   EXPECT_EQ(result.dimension(2), output_rows);
99   EXPECT_EQ(result.dimension(1), output_cols);
100   EXPECT_EQ(result.dimension(0), num_batches);
101 
102   for (int b = 0; b < num_batches; ++b) {
103     for (int d = 0; d < depth; ++d) {
104       for (int i = 0; i < output_rows; ++i) {
105         for (int j = 0; j < output_cols; ++j) {
106           float expected = -10000.f;
107           for (int r = 0; r < patch_rows; ++r) {
108             for (int c = 0; c < patch_cols; ++c) {
109               expected = (std::max)(expected, input(b, c + j, r + i, d));
110             }
111           }
112           if (result(b, j, i, d) != expected) {
113             std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
114                       << " " << result(b, j, i, d) << " vs " << expected
115                       << std::endl;
116           }
117           EigenApprox(result(b, j, i, d), expected);
118         }
119       }
120     }
121   }
122 }
123 
TEST(EigenPoolingTest,Cuboid)124 TEST(EigenPoolingTest, Cuboid) {
125   const int channels = 10;
126   const int input_planes = 5;
127   const int input_rows = 5;
128   const int input_cols = 5;
129   const int num_batches = 13;
130   const int patch_rows = 4;
131   const int patch_cols = 3;
132   const int patch_planes = 2;
133   const int output_rows = 2;
134   const int output_cols = 3;
135   const int output_planes = 4;
136 
137   Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
138                          num_batches);
139   Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
140                           num_batches);
141   input = input.constant(11.0f) + input.random();
142   result.setRandom();
143   result = result.constant(-1000.0f);
144 
145   // Max pooling using a 4x3x2 window and a stride of 1.
146   const int stride = 1;
147   result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
148                             stride, stride, PADDING_VALID);
149 
150   EXPECT_EQ(result.dimension(0), channels);
151   EXPECT_EQ(result.dimension(1), output_planes);
152   EXPECT_EQ(result.dimension(2), output_rows);
153   EXPECT_EQ(result.dimension(3), output_cols);
154   EXPECT_EQ(result.dimension(4), num_batches);
155 
156   for (int b = 0; b < num_batches; ++b) {
157     for (int d = 0; d < channels; ++d) {
158       for (int i = 0; i < output_planes; ++i) {
159         for (int j = 0; j < output_rows; ++j) {
160           for (int k = 0; k < output_cols; ++k) {
161             float expected = -10000.f;
162             for (int p = 0; p < patch_planes; ++p) {
163               for (int r = 0; r < patch_rows; ++r) {
164                 for (int c = 0; c < patch_cols; ++c) {
165                   expected =
166                       (std::max)(expected, input(d, p + i, r + j, c + k, b));
167                 }
168               }
169             }
170             if (result(d, i, j, k, b) != expected) {
171               std::cout << "at d=" << d << " b=" << b << " i=" << i
172                         << " j=" << j << " k=" << k << " "
173                         << result(d, i, j, k, b) << " vs " << expected
174                         << std::endl;
175             }
176             EigenApprox(result(d, i, j, k, b), expected);
177           }
178         }
179       }
180     }
181   }
182 }
183 
TEST(EigenPoolingTest,CuboidRowMajor)184 TEST(EigenPoolingTest, CuboidRowMajor) {
185   const int channels = 10;
186   const int input_planes = 5;
187   const int input_rows = 5;
188   const int input_cols = 5;
189   const int num_batches = 13;
190   const int patch_rows = 4;
191   const int patch_cols = 3;
192   const int patch_planes = 2;
193   const int output_rows = 2;
194   const int output_cols = 3;
195   const int output_planes = 4;
196 
197   Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
198                                    input_planes, channels);
199   Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
200                                     output_planes, channels);
201   input = input.constant(11.0f) + input.random();
202   result.setRandom();
203   result = result.constant(-1000.0f);
204 
205   // Max pooling using a 4x3x2 window and a stride of 1.
206   const int stride = 1;
207   result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
208                             stride, stride, PADDING_VALID);
209 
210   EXPECT_EQ(result.dimension(4), channels);
211   EXPECT_EQ(result.dimension(3), output_planes);
212   EXPECT_EQ(result.dimension(2), output_rows);
213   EXPECT_EQ(result.dimension(1), output_cols);
214   EXPECT_EQ(result.dimension(0), num_batches);
215 
216   for (int b = 0; b < num_batches; ++b) {
217     for (int d = 0; d < channels; ++d) {
218       for (int i = 0; i < output_planes; ++i) {
219         for (int j = 0; j < output_rows; ++j) {
220           for (int k = 0; k < output_cols; ++k) {
221             float expected = -10000.f;
222             for (int p = 0; p < patch_planes; ++p) {
223               for (int r = 0; r < patch_rows; ++r) {
224                 for (int c = 0; c < patch_cols; ++c) {
225                   expected =
226                       (std::max)(expected, input(b, c + k, r + j, p + i, d));
227                 }
228               }
229             }
230             if (result(b, k, j, i, d) != expected) {
231               std::cout << "at d=" << d << " b=" << b << " i=" << i
232                         << " j=" << j << " k=" << k << " "
233                         << result(b, k, j, i, d) << " vs " << expected
234                         << std::endl;
235             }
236             EigenApprox(result(b, k, j, i, d), expected);
237           }
238         }
239       }
240     }
241   }
242 }
243 
TEST(EigenPoolingTest,ValidCuboid)244 TEST(EigenPoolingTest, ValidCuboid) {
245   const int channels = 10;
246   const int input_planes = 5;
247   const int input_rows = 5;
248   const int input_cols = 5;
249   const int num_batches = 13;
250   const int patch_rows = 4;
251   const int patch_cols = 3;
252   const int patch_planes = 2;
253   const int output_rows = 2;
254   const int output_cols = 3;
255   const int output_planes = 4;
256 
257   Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
258                          num_batches);
259   Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
260                           num_batches);
261   input = input.constant(11.0f) + input.random();
262   result.setRandom();
263   result = result.constant(-1000.0f);
264 
265   // Max pooling using a 4x3x2 window and a stride of 1.
266   const int stride = 1;
267   result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
268                             stride, stride, PADDING_VALID);
269 
270   EXPECT_EQ(result.dimension(0), channels);
271   EXPECT_EQ(result.dimension(1), output_planes);
272   EXPECT_EQ(result.dimension(2), output_rows);
273   EXPECT_EQ(result.dimension(3), output_cols);
274   EXPECT_EQ(result.dimension(4), num_batches);
275 
276   for (int b = 0; b < num_batches; ++b) {
277     for (int d = 0; d < channels; ++d) {
278       for (int i = 0; i < output_planes; ++i) {
279         for (int j = 0; j < output_rows; ++j) {
280           for (int k = 0; k < output_cols; ++k) {
281             float expected_sum = 0.0f;
282             int expected_count = 0;
283             for (int p = 0; p < patch_planes; ++p) {
284               for (int r = 0; r < patch_rows; ++r) {
285                 for (int c = 0; c < patch_cols; ++c) {
286                   expected_sum += input(d, p + i, r + j, c + k, b);
287                   expected_count++;
288                 }
289               }
290             }
291             const float expected = expected_sum / expected_count;
292             if (result(d, i, j, k, b) != expected) {
293               std::cout << "at d=" << d << " b=" << b << " i=" << i
294                         << " j=" << j << " k=" << k << " "
295                         << result(d, i, j, k, b) << " vs " << expected
296                         << std::endl;
297             }
298             EigenApprox(result(d, i, j, k, b), expected);
299           }
300         }
301       }
302     }
303   }
304 }
305 
TEST(EigenPoolingTest,ValidCuboidRowMajor)306 TEST(EigenPoolingTest, ValidCuboidRowMajor) {
307   const int channels = 10;
308   const int input_planes = 5;
309   const int input_rows = 5;
310   const int input_cols = 5;
311   const int num_batches = 13;
312   const int patch_rows = 4;
313   const int patch_cols = 3;
314   const int patch_planes = 2;
315   const int output_rows = 2;
316   const int output_cols = 3;
317   const int output_planes = 4;
318 
319   Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
320                                    input_planes, channels);
321   Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
322                                     output_planes, channels);
323   input = input.constant(11.0f) + input.random();
324   result.setRandom();
325   result = result.constant(-1000.0f);
326 
327   // Max pooling using a 4x3x2 window and a stride of 1.
328   const int stride = 1;
329   result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
330                             stride, stride, PADDING_VALID);
331 
332   EXPECT_EQ(result.dimension(4), channels);
333   EXPECT_EQ(result.dimension(3), output_planes);
334   EXPECT_EQ(result.dimension(2), output_rows);
335   EXPECT_EQ(result.dimension(1), output_cols);
336   EXPECT_EQ(result.dimension(0), num_batches);
337 
338   for (int b = 0; b < num_batches; ++b) {
339     for (int d = 0; d < channels; ++d) {
340       for (int i = 0; i < output_planes; ++i) {
341         for (int j = 0; j < output_rows; ++j) {
342           for (int k = 0; k < output_cols; ++k) {
343             float expected_sum = 0.0f;
344             int expected_count = 0;
345             for (int p = 0; p < patch_planes; ++p) {
346               for (int r = 0; r < patch_rows; ++r) {
347                 for (int c = 0; c < patch_cols; ++c) {
348                   expected_sum += input(b, c + k, r + j, p + i, d);
349                   expected_count++;
350                 }
351               }
352             }
353             const float expected = expected_sum / expected_count;
354             if (result(b, k, j, i, d) != expected) {
355               std::cout << "at d=" << d << " b=" << b << " i=" << i
356                         << " j=" << j << " k=" << k << " "
357                         << result(b, k, j, i, d) << " vs " << expected
358                         << std::endl;
359             }
360             EigenApprox(result(b, k, j, i, d), expected);
361           }
362         }
363       }
364     }
365   }
366 }
367 
TEST(EigenPoolingTest,SameCuboid)368 TEST(EigenPoolingTest, SameCuboid) {
369   const int channels = 10;
370   const int input_planes = 5;
371   const int input_rows = 5;
372   const int input_cols = 5;
373   const int num_batches = 13;
374   const int patch_rows = 4;
375   const int patch_cols = 3;
376   const int patch_planes = 2;
377   const int output_rows = input_rows;
378   const int output_cols = input_cols;
379   const int output_planes = input_planes;
380 
381   Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
382                          num_batches);
383   Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
384                           num_batches);
385   input = input.constant(11.0f) + input.random();
386   result.setRandom();
387   result = result.constant(-1000.0f);
388 
389   // Max pooling using a 4x3x2 window and a stride of 1.
390   const int stride = 1;
391   result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
392                             stride, stride, PADDING_SAME);
393 
394   EXPECT_EQ(result.dimension(0), channels);
395   EXPECT_EQ(result.dimension(1), output_planes);
396   EXPECT_EQ(result.dimension(2), output_rows);
397   EXPECT_EQ(result.dimension(3), output_cols);
398   EXPECT_EQ(result.dimension(4), num_batches);
399 
400   const int pad_p = output_planes - input_planes + patch_planes - 1;
401   const int pad_r = output_rows - input_rows + patch_rows - 1;
402   const int pad_c = output_cols - input_cols + patch_cols - 1;
403 
404   // Number of pixels the input is extended with at the lower end in every
405   // dimension.
406   const int dp = pad_p / 2;
407   const int dr = pad_r / 2;
408   const int dc = pad_c / 2;
409 
410   for (int b = 0; b < num_batches; ++b) {
411     for (int d = 0; d < channels; ++d) {
412       for (int i = 0; i < output_planes; ++i) {
413         for (int j = 0; j < output_rows; ++j) {
414           for (int k = 0; k < output_cols; ++k) {
415             float expected_sum = 0.0f;
416             int expected_count = 0;
417             for (int p = 0; p < patch_planes; ++p) {
418               for (int r = 0; r < patch_rows; ++r) {
419                 for (int c = 0; c < patch_cols; ++c) {
420                   const int in_p = p + i - dp;
421                   const int in_r = r + j - dr;
422                   const int in_c = c + k - dc;
423                   if (in_p >= 0 && in_p < input_planes && in_r >= 0 &&
424                       in_r < input_rows && in_c >= 0 && in_c < input_cols) {
425                     expected_sum += input(d, in_p, in_r, in_c, b);
426                     expected_count++;
427                   }
428                 }
429               }
430             }
431             const float expected = expected_sum / expected_count;
432             if (result(d, i, j, k, b) != expected) {
433               std::cout << "at d=" << d << " b=" << b << " i=" << i
434                         << " j=" << j << " k=" << k << " "
435                         << result(d, i, j, k, b) << " vs " << expected
436                         << std::endl;
437             }
438             EigenApprox(result(d, i, j, k, b), expected);
439           }
440         }
441       }
442     }
443   }
444 }
445 
TEST(EigenPoolingTest,SameCuboidRowMajor)446 TEST(EigenPoolingTest, SameCuboidRowMajor) {
447   const int channels = 10;
448   const int input_planes = 5;
449   const int input_rows = 5;
450   const int input_cols = 5;
451   const int num_batches = 13;
452   const int patch_rows = 4;
453   const int patch_cols = 3;
454   const int patch_planes = 2;
455   const int output_rows = input_rows;
456   const int output_cols = input_cols;
457   const int output_planes = input_planes;
458 
459   Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
460                                    input_planes, channels);
461   Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
462                                     output_planes, channels);
463   input = input.constant(11.0f) + input.random();
464   result.setRandom();
465   result = result.constant(-1000.0f);
466 
467   // Max pooling using a 4x3x2 window and a stride of 1.
468   const int stride = 1;
469   result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
470                             stride, stride, PADDING_SAME);
471 
472   EXPECT_EQ(result.dimension(4), channels);
473   EXPECT_EQ(result.dimension(3), output_planes);
474   EXPECT_EQ(result.dimension(2), output_rows);
475   EXPECT_EQ(result.dimension(1), output_cols);
476   EXPECT_EQ(result.dimension(0), num_batches);
477 
478   const int pad_p = output_planes - input_planes + patch_planes - 1;
479   const int pad_r = output_rows - input_rows + patch_rows - 1;
480   const int pad_c = output_cols - input_cols + patch_cols - 1;
481 
482   // Number of pixels the input is extended with at the lower end in every
483   // dimension.
484   const int dp = pad_p / 2;
485   const int dr = pad_r / 2;
486   const int dc = pad_c / 2;
487 
488   for (int b = 0; b < num_batches; ++b) {
489     for (int d = 0; d < channels; ++d) {
490       for (int i = 0; i < output_planes; ++i) {
491         for (int j = 0; j < output_rows; ++j) {
492           for (int k = 0; k < output_cols; ++k) {
493             float expected_sum = 0.0f;
494             int expected_count = 0;
495             for (int p = 0; p < patch_planes; ++p) {
496               for (int r = 0; r < patch_rows; ++r) {
497                 for (int c = 0; c < patch_cols; ++c) {
498                   const int in_p = p + i - dp;
499                   const int in_r = r + j - dr;
500                   const int in_c = c + k - dc;
501                   if (in_p >= 0 && in_p < input_planes && in_r >= 0 &&
502                       in_r < input_rows && in_c >= 0 && in_c < input_cols) {
503                     expected_sum += input(b, in_c, in_r, in_p, d);
504                     expected_count++;
505                   }
506                 }
507               }
508             }
509             const float expected = expected_sum / expected_count;
510             if (result(b, k, j, i, d) != expected) {
511               std::cout << "at d=" << d << " b=" << b << " i=" << i
512                         << " j=" << j << " k=" << k << " "
513                         << result(b, k, j, i, d) << " vs " << expected
514                         << std::endl;
515             }
516             EigenApprox(result(b, k, j, i, d), expected);
517           }
518         }
519       }
520     }
521   }
522 }
523 
TEST(EigenPoolingTest,Strided)524 TEST(EigenPoolingTest, Strided) {
525   const int depth = 10;
526   const int input_rows = 5;
527   const int input_cols = 5;
528   const int num_batches = 13;
529   const int patch_rows = 3;
530   const int patch_cols = 3;
531   const int output_rows = 2;
532   const int output_cols = 2;
533 
534   Tensor<float, 4> input(depth, input_rows, input_cols, num_batches);
535   Tensor<float, 4> result(depth, output_rows, output_cols, num_batches);
536   input = input.constant(11.0f) + input.random();
537   result.setRandom();
538 
539   // Max pooling using a 3x3 window and a stride of 2.
540   int stride = 2;
541   result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
542                              PADDING_VALID);
543 
544   EXPECT_EQ(result.dimension(0), depth);
545   EXPECT_EQ(result.dimension(1), output_rows);
546   EXPECT_EQ(result.dimension(2), output_cols);
547   EXPECT_EQ(result.dimension(3), num_batches);
548 
549   for (int b = 0; b < num_batches; ++b) {
550     for (int d = 0; d < depth; ++d) {
551       for (int i = 0; i < output_rows; ++i) {
552         for (int j = 0; j < output_cols; ++j) {
553           float expected = -10000.f;
554           for (int r = 0; r < patch_rows; ++r) {
555             for (int c = 0; c < patch_cols; ++c) {
556               expected = (std::max)(
557                   expected, input(d, r + stride * i, c + stride * j, b));
558             }
559           }
560           if (result(d, i, j, b) != expected) {
561             std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
562                       << " " << result(d, i, j, b) << " vs " << expected
563                       << std::endl;
564           }
565           EigenApprox(result(d, i, j, b), expected);
566         }
567       }
568     }
569   }
570 }
571 
TEST(EigenPoolingTest,StridedRowMajor)572 TEST(EigenPoolingTest, StridedRowMajor) {
573   const int depth = 10;
574   const int input_rows = 5;
575   const int input_cols = 5;
576   const int num_batches = 13;
577   const int patch_rows = 3;
578   const int patch_cols = 3;
579   const int output_rows = 2;
580   const int output_cols = 2;
581 
582   Tensor<float, 4, RowMajor> input(num_batches, input_cols, input_rows, depth);
583   Tensor<float, 4, RowMajor> result(num_batches, output_cols, output_rows,
584                                     depth);
585   input = input.constant(11.0f) + input.random();
586   result.setRandom();
587 
588   // Max pooling using a 3x3 window and a stride of 2.
589   int stride = 2;
590   result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
591                              PADDING_VALID);
592 
593   EXPECT_EQ(result.dimension(3), depth);
594   EXPECT_EQ(result.dimension(2), output_rows);
595   EXPECT_EQ(result.dimension(1), output_cols);
596   EXPECT_EQ(result.dimension(0), num_batches);
597 
598   for (int b = 0; b < num_batches; ++b) {
599     for (int d = 0; d < depth; ++d) {
600       for (int i = 0; i < output_rows; ++i) {
601         for (int j = 0; j < output_cols; ++j) {
602           float expected = -10000.f;
603           for (int r = 0; r < patch_rows; ++r) {
604             for (int c = 0; c < patch_cols; ++c) {
605               expected = (std::max)(
606                   expected, input(b, c + stride * j, r + stride * i, d));
607             }
608           }
609           if (result(b, j, i, d) != expected) {
610             std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
611                       << " " << result(b, j, i, d) << " vs " << expected
612                       << std::endl;
613           }
614           EigenApprox(result(b, j, i, d), expected);
615         }
616       }
617     }
618   }
619 }
620 
TEST(EigenPoolingTest,StridedCuboid)621 TEST(EigenPoolingTest, StridedCuboid) {
622   const int channels = 10;
623   const int input_planes = 5;
624   const int input_rows = 5;
625   const int input_cols = 5;
626   const int num_batches = 13;
627   const int patch_planes = 3;
628   const int patch_rows = 3;
629   const int patch_cols = 3;
630   const int output_planes = 2;
631   const int output_rows = 2;
632   const int output_cols = 2;
633 
634   Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
635                          num_batches);
636   Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
637                           num_batches);
638   input = input.constant(11.0f) + input.random();
639   result.setRandom();
640 
641   // Max pooling using a 3x3x3 window and a stride of 2.
642   int stride = 2;
643   result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
644                             stride, stride, PADDING_VALID);
645 
646   EXPECT_EQ(result.dimension(0), channels);
647   EXPECT_EQ(result.dimension(1), output_planes);
648   EXPECT_EQ(result.dimension(2), output_rows);
649   EXPECT_EQ(result.dimension(3), output_cols);
650   EXPECT_EQ(result.dimension(4), num_batches);
651 
652   for (int b = 0; b < num_batches; ++b) {
653     for (int d = 0; d < channels; ++d) {
654       for (int i = 0; i < output_planes; ++i) {
655         for (int j = 0; j < output_rows; ++j) {
656           for (int k = 0; k < output_cols; ++k) {
657             float expected = -10000.f;
658             for (int p = 0; p < patch_planes; ++p) {
659               for (int r = 0; r < patch_rows; ++r) {
660                 for (int c = 0; c < patch_cols; ++c) {
661                   expected = (std::max)(expected,
662                                         input(d, p + stride * i, r + stride * j,
663                                               c + stride * k, b));
664                 }
665               }
666             }
667             if (result(d, i, j, k, b) != expected) {
668               std::cout << "at d=" << d << " b=" << b << " i=" << i
669                         << " j=" << j << " " << k << " "
670                         << result(d, i, j, k, b) << " vs " << expected
671                         << std::endl;
672             }
673             EigenApprox(result(d, i, j, k, b), expected);
674           }
675         }
676       }
677     }
678   }
679 }
680 
TEST(EigenPoolingTest,StridedCuboidRowMajor)681 TEST(EigenPoolingTest, StridedCuboidRowMajor) {
682   const int channels = 10;
683   const int input_planes = 5;
684   const int input_rows = 5;
685   const int input_cols = 5;
686   const int num_batches = 13;
687   const int patch_planes = 3;
688   const int patch_rows = 3;
689   const int patch_cols = 3;
690   const int output_planes = 2;
691   const int output_rows = 2;
692   const int output_cols = 2;
693 
694   Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
695                                    input_planes, channels);
696   Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
697                                     output_planes, channels);
698   input = input.constant(11.0f) + input.random();
699   result.setRandom();
700 
701   // Max pooling using a 3x3x3 window and a stride of 2.
702   int stride = 2;
703   result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
704                             stride, stride, PADDING_VALID);
705 
706   EXPECT_EQ(result.dimension(4), channels);
707   EXPECT_EQ(result.dimension(3), output_planes);
708   EXPECT_EQ(result.dimension(2), output_rows);
709   EXPECT_EQ(result.dimension(1), output_cols);
710   EXPECT_EQ(result.dimension(0), num_batches);
711 
712   for (int b = 0; b < num_batches; ++b) {
713     for (int d = 0; d < channels; ++d) {
714       for (int i = 0; i < output_planes; ++i) {
715         for (int j = 0; j < output_rows; ++j) {
716           for (int k = 0; k < output_cols; ++k) {
717             float expected = -10000.f;
718             for (int p = 0; p < patch_planes; ++p) {
719               for (int r = 0; r < patch_rows; ++r) {
720                 for (int c = 0; c < patch_cols; ++c) {
721                   expected = (std::max)(expected,
722                                         input(b, c + stride * k, r + stride * j,
723                                               p + stride * i, d));
724                 }
725               }
726             }
727             if (result(b, k, j, i, d) != expected) {
728               std::cout << "at d=" << d << " b=" << b << " i=" << i
729                         << " j=" << j << " " << k << " "
730                         << result(b, k, j, i, d) << " vs " << expected
731                         << std::endl;
732             }
733             EigenApprox(result(b, k, j, i, d), expected);
734           }
735         }
736       }
737     }
738   }
739 }
740 
741 }  // namespace Eigen
742