• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 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/framework/allocator.h"
17 #include "tensorflow/core/framework/fake_input.h"
18 #include "tensorflow/core/framework/node_def_builder.h"
19 #include "tensorflow/core/framework/op_kernel.h"
20 #include "tensorflow/core/framework/register_types.h"
21 #include "tensorflow/core/framework/tensor.h"
22 #include "tensorflow/core/framework/tensor_testutil.h"
23 #include "tensorflow/core/framework/tensor_util.h"
24 #include "tensorflow/core/framework/types.h"
25 #include "tensorflow/core/framework/types.pb.h"
26 #include "tensorflow/core/kernels/ops_testutil.h"
27 #include "tensorflow/core/kernels/ops_util.h"
28 #include "tensorflow/core/lib/core/status_test_util.h"
29 #include "tensorflow/core/lib/strings/str_util.h"
30 #include "tensorflow/core/platform/test.h"
31 
32 namespace tensorflow {
33 
34 class MirrorPadOpTest : public OpsTestBase {
35  protected:
36   template <typename T>
MakeOp(const string & mode)37   void MakeOp(const string& mode) {
38     TF_EXPECT_OK(NodeDefBuilder("mirror_pad_op", "MirrorPad")
39                      .Input(FakeInput(DataTypeToEnum<T>::value))
40                      .Input(FakeInput(DT_INT32))
41                      .Attr("mode", mode)
42                      .Finalize(node_def()));
43     TF_EXPECT_OK(InitOp());
44   }
45 };
46 
47 #define REGISTER_TEST(T)                                                     \
48   TEST_F(MirrorPadOpTest, TestMirrorPadReflect##T) {                         \
49     MakeOp<T>("REFLECT");                                                    \
50     AddInputFromArray<T>(TensorShape({1, 2, 3, 1}), {1, 2, 3, 4, 5, 6});     \
51     AddInputFromArray<int32>(TensorShape({4, 2}), {0, 0, 1, 1, 2, 2, 0, 0}); \
52     TF_ASSERT_OK(RunOpKernel());                                             \
53                                                                              \
54     Tensor expected(allocator(), DataTypeToEnum<T>::value,                   \
55                     TensorShape({1, 4, 7, 1}));                              \
56     test::FillValues<T>(&expected,                                           \
57                         {6, 5, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 2, 1,           \
58                          6, 5, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 2, 1});         \
59     test::ExpectTensorEqual<T>(expected, *GetOutput(0));                     \
60   }                                                                          \
61                                                                              \
62   TEST_F(MirrorPadOpTest, TestMirrorPadSymmetric##T) {                       \
63     MakeOp<T>("SYMMETRIC");                                                  \
64     AddInputFromArray<T>(TensorShape({1, 2, 1, 3}), {1, 2, 3, 4, 5, 6});     \
65     AddInputFromArray<int32>(TensorShape({4, 2}), {1, 1, 0, 0, 0, 0, 2, 2}); \
66     TF_ASSERT_OK(RunOpKernel());                                             \
67                                                                              \
68     Tensor expected(allocator(), DataTypeToEnum<T>::value,                   \
69                     TensorShape({3, 2, 1, 7}));                              \
70     test::FillValues<T>(                                                     \
71         &expected,                                                           \
72         {2, 1, 1, 2, 3, 3, 2, 5, 4, 4, 5, 6, 6, 5, 2, 1, 1, 2, 3, 3, 2,      \
73          5, 4, 4, 5, 6, 6, 5, 2, 1, 1, 2, 3, 3, 2, 5, 4, 4, 5, 6, 6, 5});    \
74     test::ExpectTensorEqual<T>(expected, *GetOutput(0));                     \
75   }
76 
77 REGISTER_TEST(float)
REGISTER_TEST(double)78 REGISTER_TEST(double)
79 REGISTER_TEST(uint8)
80 REGISTER_TEST(uint16)
81 REGISTER_TEST(int8)
82 REGISTER_TEST(int16)
83 REGISTER_TEST(int32)
84 REGISTER_TEST(int64)
85 
86 #undef REGISTER_TEST
87 
88 TEST_F(MirrorPadOpTest, TestMirrorPadReflectLargeInput) {
89   MakeOp<float>("REFLECT");
90   // Generate a relatively large input
91   const int kInput = 1000;
92   const int kPad = 10;
93   const int kOutput = kInput + 2 * kPad;
94 
95   // Input:
96   //  0, 1, 2, ..., 999
97   //  0, 1, 2, ..., 999
98   //  ... (altogether 1000 lines)
99   //  0, 1, 2, ..., 999
100   AddInput<float>(TensorShape({1, kInput, kInput, 1}),
101                   [=](int i) -> float { return i % kInput; });
102   AddInputFromArray<int32>(TensorShape({4, 2}),
103                            {0, 0, kPad, kPad, kPad, kPad, 0, 0});
104   TF_ASSERT_OK(RunOpKernel());
105 
106   Tensor expected(allocator(), DT_FLOAT, TensorShape({1, kOutput, kOutput, 1}));
107   test::FillFn<float>(&expected, [=](int i) -> float {
108     i = i % kOutput;
109     if (0 <= i && i < kPad)
110       return kPad - i;
111     else if (kPad <= i && i < kInput + kPad)
112       return i - kPad;
113     else if (kInput + kPad <= i && i < kOutput)
114       return 2 * kInput + kPad - 2 - i;
115     else
116       return -1;
117   });
118 
119   test::ExpectTensorEqual<float>(expected, *GetOutput(0));
120 }
121 
TEST_F(MirrorPadOpTest,TestMirrorPadSymmetricLargeInput)122 TEST_F(MirrorPadOpTest, TestMirrorPadSymmetricLargeInput) {
123   MakeOp<float>("SYMMETRIC");
124   // Generate a relatively large input
125   const int kInput = 1000;
126   const int kPad = 10;
127   const int kOutput = kInput + 2 * kPad;
128 
129   // Input:
130   //  0, 1, 2, ..., 999
131   //  0, 1, 2, ..., 999
132   //  ... (altogether 1000 lines)
133   //  0, 1, 2, ..., 999
134   AddInput<float>(TensorShape({1, kInput, kInput, 1}),
135                   [=](int i) -> float { return i % kInput; });
136   AddInputFromArray<int32>(TensorShape({4, 2}),
137                            {0, 0, kPad, kPad, kPad, kPad, 0, 0});
138   TF_ASSERT_OK(RunOpKernel());
139 
140   Tensor expected(allocator(), DT_FLOAT, TensorShape({1, kOutput, kOutput, 1}));
141   test::FillFn<float>(&expected, [=](int i) -> float {
142     i = i % kOutput;
143     if (0 <= i && i < kPad)
144       return kPad - i - 1;
145     else if (kPad <= i && i < kInput + kPad)
146       return i - kPad;
147     else if (kInput + kPad <= i && i < kOutput)
148       return 2 * kInput + kPad - 1 - i;
149     else
150       return -1;
151   });
152 
153   test::ExpectTensorEqual<float>(expected, *GetOutput(0));
154 }
155 
156 class MirrorPadGradOpTest : public OpsTestBase {
157  protected:
158   template <typename T>
MakeOp(const string & mode)159   void MakeOp(const string& mode) {
160     TF_EXPECT_OK(NodeDefBuilder("mirror_pad_grad_op", "MirrorPadGrad")
161                      .Input(FakeInput(DataTypeToEnum<T>::value))
162                      .Input(FakeInput(DT_INT32))
163                      .Attr("mode", mode)
164                      .Finalize(node_def()));
165     TF_EXPECT_OK(InitOp());
166   }
167 };
168 
169 #define REGISTER_TEST(T)                                                      \
170   TEST_F(MirrorPadGradOpTest, TestMirrorPadGradReflect##T) {                  \
171     MakeOp<T>("REFLECT");                                                     \
172     AddInput<T>(TensorShape({1, 4, 7, 1}), [](int i) -> T { return i % 7; }); \
173     AddInputFromArray<int32>(TensorShape({4, 2}), {0, 0, 1, 1, 2, 2, 0, 0});  \
174     TF_ASSERT_OK(RunOpKernel());                                              \
175                                                                               \
176     Tensor expected(allocator(), DataTypeToEnum<T>::value,                    \
177                     TensorShape({1, 2, 3, 1}));                               \
178     test::FillValues<T>(&expected, {16, 18, 8, 16, 18, 8});                   \
179     test::ExpectTensorEqual<T>(expected, *GetOutput(0));                      \
180   }                                                                           \
181                                                                               \
182   TEST_F(MirrorPadGradOpTest, TestMirrorPadGradSymmetric##T) {                \
183     MakeOp<T>("SYMMETRIC");                                                   \
184     AddInput<T>(TensorShape({3, 2, 1, 7}), [](int i) -> T { return i % 7; }); \
185     AddInputFromArray<int32>(TensorShape({4, 2}), {1, 1, 0, 0, 0, 0, 2, 2});  \
186     TF_ASSERT_OK(RunOpKernel());                                              \
187                                                                               \
188     Tensor expected(allocator(), DataTypeToEnum<T>::value,                    \
189                     TensorShape({1, 2, 1, 3}));                               \
190     test::FillValues<T>(&expected, {9, 27, 27, 9, 27, 27});                   \
191     test::ExpectTensorEqual<T>(expected, *GetOutput(0));                      \
192   }
193 
194 REGISTER_TEST(float)
195 REGISTER_TEST(double)
196 REGISTER_TEST(uint8)
197 REGISTER_TEST(uint16)
198 REGISTER_TEST(int8)
199 REGISTER_TEST(int16)
200 REGISTER_TEST(int32)
201 REGISTER_TEST(int64)
202 
203 #undef REGISTER_TEST
204 
205 }  // namespace tensorflow
206