@@ -44,11 +44,19 @@ class BatchToSpaceNDOpModel : public SingleOpModel {
44
44
PopulateTensor<int >(crops_, data);
45
45
}
46
46
47
+ int input_tensor_id () { return input_; }
48
+
47
49
template <typename T>
48
50
std::vector<T> GetOutput () {
49
51
return ExtractVector<T>(output_);
50
52
}
51
53
54
+ template <typename T>
55
+ std::vector<float > GetDequantizedOutput () {
56
+ return Dequantize<T>(ExtractVector<T>(output_), GetScale (output_),
57
+ GetZeroPoint (output_));
58
+ }
59
+
52
60
int32_t GetOutputSize () { return GetTensorSize (output_); }
53
61
std::vector<int > GetOutputShape () { return GetTensorShape (output_); }
54
62
@@ -67,20 +75,20 @@ class BatchToSpaceNDOpModel : public SingleOpModel {
67
75
// m.Invoke();
68
76
class BatchToSpaceNDOpConstModel : public BatchToSpaceNDOpModel {
69
77
public:
70
- BatchToSpaceNDOpConstModel (std::initializer_list< int > input_shape ,
78
+ BatchToSpaceNDOpConstModel (const TensorData& input ,
71
79
std::initializer_list<int > block_shape,
72
80
std::initializer_list<int > crops,
73
- const TensorType& type = TensorType_FLOAT32 ) {
81
+ const TensorData& output ) {
74
82
int spatial_dims = static_cast <int >(block_shape.size ());
75
- input_ = AddInput ({type, input_shape} );
83
+ input_ = AddInput (input );
76
84
block_shape_ = AddConstInput (TensorType_INT32, block_shape, {spatial_dims});
77
85
crops_ = AddConstInput (TensorType_INT32, crops, {spatial_dims, 2 });
78
- output_ = AddOutput (type );
86
+ output_ = AddOutput (output );
79
87
80
88
SetBuiltinOp (BuiltinOperator_BATCH_TO_SPACE_ND,
81
89
BuiltinOptions_BatchToSpaceNDOptions,
82
90
CreateBatchToSpaceNDOptions (builder_).Union ());
83
- BuildInterpreter ({input_shape });
91
+ BuildInterpreter ({GetShape (input_) });
84
92
}
85
93
};
86
94
@@ -94,23 +102,32 @@ class BatchToSpaceNDOpConstModel : public BatchToSpaceNDOpModel {
94
102
// m.Invoke();
95
103
class BatchToSpaceNDOpDynamicModel : public BatchToSpaceNDOpModel {
96
104
public:
97
- BatchToSpaceNDOpDynamicModel (std::initializer_list< int > input_shape ,
98
- const TensorType& type = TensorType_FLOAT32 ) {
99
- input_ = AddInput ({type, input_shape} );
105
+ BatchToSpaceNDOpDynamicModel (const TensorData& input ,
106
+ const TensorData& output ) {
107
+ input_ = AddInput (input );
100
108
block_shape_ = AddInput (TensorType_INT32);
101
109
crops_ = AddInput (TensorType_INT32);
102
- output_ = AddOutput (type );
110
+ output_ = AddOutput (output );
103
111
104
- int spatial_dims = static_cast <int >(input_shape .size ()) - 2 ;
112
+ int spatial_dims = static_cast <int >(GetShape (input_) .size ()) - 2 ;
105
113
SetBuiltinOp (BuiltinOperator_BATCH_TO_SPACE_ND,
106
114
BuiltinOptions_BatchToSpaceNDOptions,
107
115
CreateBatchToSpaceNDOptions (builder_).Union ());
108
- BuildInterpreter ({input_shape , {spatial_dims}, {spatial_dims, 2 }});
116
+ BuildInterpreter ({GetShape (input_) , {spatial_dims}, {spatial_dims, 2 }});
109
117
}
110
118
};
111
119
120
+ template <typename integer_type>
121
+ float GetTolerance (float min, float max) {
122
+ float kQuantizedStep =
123
+ (max - min) / (std::numeric_limits<integer_type>::max () -
124
+ std::numeric_limits<integer_type>::min ());
125
+ return kQuantizedStep ;
126
+ }
127
+
112
128
TEST (BatchToSpaceNDOpTest, SimpleConstTest) {
113
- BatchToSpaceNDOpConstModel m ({4 , 2 , 2 , 1 }, {2 , 2 }, {0 , 0 , 0 , 0 });
129
+ BatchToSpaceNDOpConstModel m ({TensorType_FLOAT32, {4 , 2 , 2 , 1 }}, {2 , 2 },
130
+ {0 , 0 , 0 , 0 }, {TensorType_FLOAT32});
114
131
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
115
132
ASSERT_EQ (m.Invoke (), kTfLiteOk );
116
133
EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({1 , 4 , 4 , 1 }));
@@ -120,8 +137,8 @@ TEST(BatchToSpaceNDOpTest, SimpleConstTest) {
120
137
}
121
138
122
139
TEST (BatchToSpaceNDOpTest, SimpleConstTestInt8) {
123
- BatchToSpaceNDOpConstModel m ({4 , 2 , 2 , 1 }, {2 , 2 }, { 0 , 0 , 0 , 0 },
124
- TensorType_INT8);
140
+ BatchToSpaceNDOpConstModel m ({TensorType_INT8, { 4 , 2 , 2 , 1 }} , {2 , 2 },
141
+ { 0 , 0 , 0 , 0 }, { TensorType_INT8} );
125
142
m.SetInput <int8_t >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
126
143
ASSERT_EQ (m.Invoke (), kTfLiteOk );
127
144
EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({1 , 4 , 4 , 1 }));
@@ -131,7 +148,8 @@ TEST(BatchToSpaceNDOpTest, SimpleConstTestInt8) {
131
148
}
132
149
133
150
TEST (BatchToSpaceNDOpTest, BatchOneConstTest) {
134
- BatchToSpaceNDOpConstModel m ({1 , 2 , 2 , 1 }, {1 , 1 }, {0 , 0 , 0 , 0 });
151
+ BatchToSpaceNDOpConstModel m ({TensorType_FLOAT32, {1 , 2 , 2 , 1 }}, {1 , 1 },
152
+ {0 , 0 , 0 , 0 }, {TensorType_FLOAT32});
135
153
m.SetInput <float >({1 , 2 , 3 , 4 });
136
154
ASSERT_EQ (m.Invoke (), kTfLiteOk );
137
155
EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({1 , 2 , 2 , 1 }));
@@ -144,16 +162,17 @@ TEST(BatchToSpaceNDOpTest, SimpleConstTestInt8EmptyOutput) {
144
162
return ;
145
163
}
146
164
147
- BatchToSpaceNDOpConstModel m ({4 , 2 , 2 , 1 }, { 2 , 2 }, {0 , 0 , 2 , 2 },
148
- TensorType_INT8);
165
+ BatchToSpaceNDOpConstModel m ({TensorType_INT8, { 4 , 2 , 2 , 1 }}, {2 , 2 },
166
+ { 0 , 0 , 2 , 2 }, { TensorType_INT8} );
149
167
m.SetInput <int8_t >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
150
168
ASSERT_EQ (m.Invoke (), kTfLiteOk );
151
169
EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({1 , 4 , 0 , 1 }));
152
170
EXPECT_THAT (m.GetOutputSize (), 0 );
153
171
}
154
172
155
173
TEST (BatchToSpaceNDOpTest, SimpleDynamicTest) {
156
- BatchToSpaceNDOpDynamicModel m ({4 , 2 , 2 , 1 });
174
+ BatchToSpaceNDOpDynamicModel m ({TensorType_FLOAT32, {4 , 2 , 2 , 1 }},
175
+ {TensorType_FLOAT32});
157
176
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
158
177
m.SetBlockShape ({2 , 2 });
159
178
m.SetCrops ({0 , 0 , 0 , 0 });
@@ -165,7 +184,8 @@ TEST(BatchToSpaceNDOpTest, SimpleDynamicTest) {
165
184
}
166
185
167
186
TEST (BatchToSpaceNDOpTest, SimpleDynamicTestInt8) {
168
- BatchToSpaceNDOpDynamicModel m ({4 , 2 , 2 , 1 }, TensorType_INT8);
187
+ BatchToSpaceNDOpDynamicModel m ({TensorType_INT8, {4 , 2 , 2 , 1 }},
188
+ {TensorType_INT8});
169
189
m.SetInput <int8_t >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
170
190
m.SetBlockShape ({2 , 2 });
171
191
m.SetCrops ({0 , 0 , 0 , 0 });
@@ -177,7 +197,8 @@ TEST(BatchToSpaceNDOpTest, SimpleDynamicTestInt8) {
177
197
}
178
198
179
199
TEST (BatchToSpaceNDOpTest, InvalidCropsDynamicTest) {
180
- BatchToSpaceNDOpDynamicModel m ({4 , 2 , 2 , 1 });
200
+ BatchToSpaceNDOpDynamicModel m ({TensorType_FLOAT32, {4 , 2 , 2 , 1 }},
201
+ {TensorType_FLOAT32});
181
202
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
182
203
m.SetBlockShape ({2 , 2 });
183
204
m.SetCrops ({0 , 0 , -1 , 0 });
@@ -190,7 +211,8 @@ TEST(BatchToSpaceNDOpTest, SimpleDynamicTestInt8EmptyOutput) {
190
211
return ;
191
212
}
192
213
193
- BatchToSpaceNDOpDynamicModel m ({4 , 2 , 2 , 1 }, TensorType_INT8);
214
+ BatchToSpaceNDOpDynamicModel m ({TensorType_INT8, {4 , 2 , 2 , 1 }},
215
+ {TensorType_INT8});
194
216
m.SetInput <int8_t >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
195
217
m.SetBlockShape ({2 , 2 });
196
218
m.SetCrops ({2 , 2 , 0 , 0 });
@@ -201,18 +223,23 @@ TEST(BatchToSpaceNDOpTest, SimpleDynamicTestInt8EmptyOutput) {
201
223
202
224
#if GTEST_HAS_DEATH_TEST
203
225
TEST (BatchToSpaceNDOpTest, InvalidShapeTest) {
204
- EXPECT_DEATH (BatchToSpaceNDOpConstModel ({3 , 2 , 2 , 1 }, {2 , 2 }, {0 , 0 , 0 , 0 }),
205
- " Cannot allocate tensors" );
226
+ EXPECT_DEATH (
227
+ BatchToSpaceNDOpConstModel ({TensorType_FLOAT32, {3 , 2 , 2 , 1 }}, {2 , 2 },
228
+ {0 , 0 , 0 , 0 }, {TensorType_FLOAT32}),
229
+ " Cannot allocate tensors" );
206
230
}
207
231
208
232
TEST (BatchToSpaceNDOpTest, InvalidCropsConstTest) {
209
- EXPECT_DEATH (BatchToSpaceNDOpConstModel ({3 , 2 , 2 , 1 }, {2 , 2 }, {0 , 0 , 0 , -1 }),
210
- " crops.i. >= 0 was not true." );
233
+ EXPECT_DEATH (
234
+ BatchToSpaceNDOpConstModel ({TensorType_FLOAT32, {3 , 2 , 2 , 1 }}, {2 , 2 },
235
+ {0 , 0 , 0 , -1 }, {TensorType_FLOAT32}),
236
+ " crops.i. >= 0 was not true." );
211
237
}
212
238
#endif
213
239
214
240
TEST (BatchToSpaceNDOpTest, Simple3DConstTest) {
215
- BatchToSpaceNDOpConstModel m ({4 , 4 , 1 }, {2 }, {0 , 0 });
241
+ BatchToSpaceNDOpConstModel m ({TensorType_FLOAT32, {4 , 4 , 1 }}, {2 }, {0 , 0 },
242
+ {TensorType_FLOAT32});
216
243
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
217
244
ASSERT_EQ (m.Invoke (), kTfLiteOk );
218
245
EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({2 , 8 , 1 }));
@@ -222,16 +249,52 @@ TEST(BatchToSpaceNDOpTest, Simple3DConstTest) {
222
249
}
223
250
224
251
TEST (BatchToSpaceNDOpTest, Simple3DConstTestWithCrops) {
225
- BatchToSpaceNDOpConstModel m ({4 , 4 , 1 }, {2 }, {1 , 1 });
252
+ BatchToSpaceNDOpConstModel m ({TensorType_FLOAT32, {4 , 4 , 1 }}, {2 }, {1 , 1 },
253
+ {TensorType_FLOAT32});
226
254
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
227
255
ASSERT_EQ (m.Invoke (), kTfLiteOk );
228
256
EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({2 , 6 , 1 }));
229
257
EXPECT_THAT (m.GetOutput <float >(),
230
258
ElementsAreArray ({9 , 2 , 10 , 3 , 11 , 4 , 13 , 6 , 14 , 7 , 15 , 8 }));
231
259
}
232
260
261
+ template <typename integer_dtype>
262
+ void Simple3DConstTestWithCropsQuant () {
263
+ const float kMin = -1 ;
264
+ const float kMax =
265
+ std::numeric_limits<integer_dtype>::max () /
266
+ static_cast <float >(std::numeric_limits<integer_dtype>::max () + 1 );
267
+ float kQuantizedTolerance = GetTolerance<integer_dtype>(-16 .0f , 16 .0f );
268
+ BatchToSpaceNDOpConstModel m (
269
+ {GetTensorType<integer_dtype>(), {4 , 4 , 1 }, 16 .0f * kMin , 16 .0f * kMax },
270
+ {2 }, {1 , 1 },
271
+ {GetTensorType<integer_dtype>(), {}, 16 .0f * kMin , 16 .0f * kMax });
272
+ m.QuantizeAndPopulate <integer_dtype>(
273
+ m.input_tensor_id (),
274
+ {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
275
+ m.Invoke ();
276
+ EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({2 , 6 , 1 }));
277
+ EXPECT_THAT (
278
+ m.GetDequantizedOutput <integer_dtype>(),
279
+ ElementsAreArray (ArrayFloatNear ({9 , 2 , 10 , 3 , 11 , 4 , 13 , 6 , 14 , 7 , 15 , 8 },
280
+ kQuantizedTolerance )));
281
+ }
282
+
283
+ TEST (BatchToSpaceNDOpTest, Simple3DConstTestWithCropsUINT8) {
284
+ Simple3DConstTestWithCropsQuant<uint8_t >();
285
+ }
286
+
287
+ TEST (BatchToSpaceNDOpTest, Simple3DConstTestWithCropsINT8) {
288
+ Simple3DConstTestWithCropsQuant<int8_t >();
289
+ }
290
+
291
+ TEST (BatchToSpaceNDOpTest, Simple3DConstTestWithCropsINT16) {
292
+ Simple3DConstTestWithCropsQuant<int16_t >();
293
+ }
294
+
233
295
TEST (BatchToSpaceNDOpTest, Simple3DDynamicTest) {
234
- BatchToSpaceNDOpDynamicModel m ({4 , 4 , 1 });
296
+ BatchToSpaceNDOpDynamicModel m ({TensorType_FLOAT32, {4 , 4 , 1 }},
297
+ {TensorType_FLOAT32});
235
298
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
236
299
m.SetBlockShape ({2 });
237
300
m.SetCrops ({0 , 0 });
@@ -243,7 +306,8 @@ TEST(BatchToSpaceNDOpTest, Simple3DDynamicTest) {
243
306
}
244
307
245
308
TEST (BatchToSpaceNDOpTest, Simple3DDynamicTestWithCrops) {
246
- BatchToSpaceNDOpDynamicModel m ({4 , 4 , 1 });
309
+ BatchToSpaceNDOpDynamicModel m ({TensorType_FLOAT32, {4 , 4 , 1 }},
310
+ {TensorType_FLOAT32});
247
311
m.SetInput <float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
248
312
m.SetBlockShape ({2 });
249
313
m.SetCrops ({1 , 1 });
@@ -253,5 +317,40 @@ TEST(BatchToSpaceNDOpTest, Simple3DDynamicTestWithCrops) {
253
317
ElementsAreArray ({9 , 2 , 10 , 3 , 11 , 4 , 13 , 6 , 14 , 7 , 15 , 8 }));
254
318
}
255
319
320
+ template <typename integer_dtype>
321
+ void Simple3DDynamicTestWithCropsQuant () {
322
+ const float kMin = -1 ;
323
+ const float kMax =
324
+ std::numeric_limits<integer_dtype>::max () /
325
+ static_cast <float >(std::numeric_limits<integer_dtype>::max () + 1 );
326
+ float kQuantizedTolerance = GetTolerance<integer_dtype>(-16.0 , 16.0 );
327
+ BatchToSpaceNDOpDynamicModel m (
328
+ {GetTensorType<integer_dtype>(), {4 , 4 , 1 }, 16 .0f * kMin , 16 .0f * kMax },
329
+ {GetTensorType<integer_dtype>(), {}, 16 .0f * kMin , 16 .0f * kMax });
330
+ m.QuantizeAndPopulate <integer_dtype>(
331
+ m.input_tensor_id (),
332
+ {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 });
333
+ m.SetBlockShape ({2 });
334
+ m.SetCrops ({1 , 1 });
335
+ m.Invoke ();
336
+ EXPECT_THAT (m.GetOutputShape (), ElementsAreArray ({2 , 6 , 1 }));
337
+ EXPECT_THAT (
338
+ m.GetDequantizedOutput <integer_dtype>(),
339
+ ElementsAreArray (ArrayFloatNear ({9 , 2 , 10 , 3 , 11 , 4 , 13 , 6 , 14 , 7 , 15 , 8 },
340
+ kQuantizedTolerance )));
341
+ }
342
+
343
+ TEST (BatchToSpaceNDOpTest, Simple3DDynamicTestWithCropsQuantUINT8) {
344
+ Simple3DDynamicTestWithCropsQuant<uint8_t >();
345
+ }
346
+
347
+ TEST (BatchToSpaceNDOpTest, Simple3DDynamicTestWithCropsQuantINT8) {
348
+ Simple3DDynamicTestWithCropsQuant<int8_t >();
349
+ }
350
+
351
+ TEST (BatchToSpaceNDOpTest, Simple3DDynamicTestWithCropsQuantINT16) {
352
+ Simple3DDynamicTestWithCropsQuant<int16_t >();
353
+ }
354
+
256
355
} // namespace
257
356
} // namespace tflite
0 commit comments