2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "kernels/LessEqual.h"
19 #include "kernels/TestUtils.h"
20 #include "luci_interpreter/TestMemoryManager.h"
22 namespace luci_interpreter
29 using namespace testing;
31 class LessEqualTest : public ::testing::Test
34 void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
36 std::unique_ptr<IMemoryManager> _memory_manager;
39 TEST_F(LessEqualTest, FloatSimple)
41 std::vector<float> x_data{
42 0.5, 0.7, 0.9, // Row 1
46 std::vector<float> y_data{
47 0.9, 0.7, 0.5, // Row 1
51 std::vector<bool> ref_output_data{
52 true, true, false, // Row 1
53 false, true, true, // Row 2
56 Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, x_data, _memory_manager.get());
57 Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, y_data, _memory_manager.get());
58 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
60 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
62 _memory_manager->allocate_memory(output_tensor);
65 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
66 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
69 TEST_F(LessEqualTest, FloatBroardcast)
71 std::vector<float> x_data{
72 0.5, 0.7, 0.9, // Row 1
77 std::vector<float> y_data{
78 0.9, 0.7, 0.5, // Row 1
81 std::vector<bool> ref_output_data{
82 true, true, false, // Row 1
83 false, true, true, // Row 2
84 true, true, false, // Row 3
87 Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({3, 3}, x_data, _memory_manager.get());
88 Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, y_data, _memory_manager.get());
89 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
91 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
93 _memory_manager->allocate_memory(output_tensor);
96 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
97 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3, 3}));
100 template <loco::DataType DType>
101 void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
103 using dtype = typename loco::DataTypeImpl<DType>::Type;
104 dtype min_value = std::numeric_limits<dtype>::min();
105 dtype max_value = std::numeric_limits<dtype>::max();
106 std::vector<dtype> x_data{min_value, 2, max_value};
108 std::vector<dtype> y_data{min_value + 1, -2, max_value};
110 std::vector<bool> ref_output_data{true, false, true};
112 Tensor x_tensor = makeInputTensor<DType>({3}, x_data, memory_manager);
113 Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
114 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
116 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
118 memory_manager->allocate_memory(output_tensor);
121 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
122 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({3}));
125 template <loco::DataType DType>
126 void checkIntegerBroadcast(luci_interpreter::IMemoryManager *memory_manager)
128 using dtype = typename loco::DataTypeImpl<DType>::Type;
129 dtype min_value = std::numeric_limits<dtype>::min();
130 dtype max_value = std::numeric_limits<dtype>::max();
131 std::vector<dtype> x_data{
132 min_value, 2, 3, // Row 1
133 4, 5, max_value, // Row 2
135 min_value, -2, max_value, // Row 4
138 std::vector<dtype> y_data{
139 min_value + 1, -2, max_value - 1, // Row 1
142 std::vector<bool> ref_output_data{
143 true, false, true, // Row 1
144 false, false, false, // Row 2
145 false, true, true, // Row 3
146 true, true, false, // Row 4
149 Tensor x_tensor = makeInputTensor<DType>({4, 3}, x_data, memory_manager);
150 Tensor y_tensor = makeInputTensor<DType>({3}, y_data, memory_manager);
151 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
153 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
155 memory_manager->allocate_memory(output_tensor);
158 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
159 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
162 TEST_F(LessEqualTest, Int32)
164 checkIntegerSimple<loco::DataType::S32>(_memory_manager.get());
165 checkIntegerBroadcast<loco::DataType::S32>(_memory_manager.get());
169 TEST_F(LessEqualTest, Int64)
171 checkIntegerSimple<loco::DataType::S64>(_memory_manager.get());
172 checkIntegerBroadcast<loco::DataType::S64>(_memory_manager.get());
176 // Choose min / max in such a way that there are exactly 256 units to avoid rounding errors.
177 const float F_MIN = -128.0 / 128.0;
178 const float F_MAX = 127.0 / 128.0;
180 TEST_F(LessEqualTest, Uint8Quantized)
182 std::vector<float> x_data{
183 0.5, 0.6, 0.7, 0.9, // Row 1
184 1, 0, 0.05, -1, // Row 2
187 std::vector<float> y_data{
188 0.9, 0.6, 0.55, 0.5, // Row 1
189 -1, 0.05, 0, 1, // Row 2
192 std::vector<bool> ref_output_data{
193 true, true, false, false, // Row 1
194 false, true, false, true, // Row 2
197 std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
198 Tensor x_tensor = makeInputTensor<DataType::U8>(
199 {1, 2, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
200 Tensor y_tensor = makeInputTensor<DataType::U8>(
201 {1, 2, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
202 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
204 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
206 _memory_manager->allocate_memory(output_tensor);
209 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
210 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
213 TEST_F(LessEqualTest, Uint8QuantizedRescale)
215 std::vector<float> x_data{
216 0.5, 0.6, 0.7, 0.9, // Row 1
217 1, 0, 0.05, -1, // Row 2
220 std::vector<float> y_data{
221 0.9, 0.6, 0.6, 0.5, // Row 1
222 -1, 0.05, 0, 1, // Row 2
225 std::vector<bool> ref_output_data{
226 true, true, false, false, // Row 1
227 false, true, false, true, // Row 2
230 std::pair<float, int32_t> x_quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
231 std::pair<float, int32_t> y_quant_param = quantizationParams<uint8_t>(F_MIN * 1.2, F_MAX * 1.5);
233 Tensor x_tensor = makeInputTensor<DataType::U8>(
234 {1, 2, 4, 1}, x_quant_param.first, x_quant_param.second, x_data, _memory_manager.get());
235 Tensor y_tensor = makeInputTensor<DataType::U8>(
236 {1, 2, 4, 1}, y_quant_param.first, y_quant_param.second, y_data, _memory_manager.get());
237 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
239 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
241 _memory_manager->allocate_memory(output_tensor);
244 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 4, 1}));
245 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
248 TEST_F(LessEqualTest, Uint8QuantizedBroadcast)
250 std::vector<float> x_data{
251 0.4, -0.8, 0.7, 0.3, // Row 1
252 -0.5, 0.1, 0, 0.5, // Row 2
253 1, 0, 0.05, -1, // Row 3
256 std::vector<float> y_data{
257 -1, 0.05, 0, 1, // Row 1
260 std::vector<bool> ref_output_data{
261 false, true, false, true, // Row 1
262 false, false, true, true, // Row 2
263 false, true, false, true, // Row 3
266 std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(F_MIN, F_MAX);
267 Tensor x_tensor = makeInputTensor<DataType::U8>(
268 {1, 3, 4, 1}, quant_param.first, quant_param.second, x_data, _memory_manager.get());
269 Tensor y_tensor = makeInputTensor<DataType::U8>(
270 {1, 1, 4, 1}, quant_param.first, quant_param.second, y_data, _memory_manager.get());
271 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
273 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
275 _memory_manager->allocate_memory(output_tensor);
278 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 3, 4, 1}));
279 EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
282 TEST_F(LessEqualTest, Input_Type_Mismatch_NEG)
284 Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
285 Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
286 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
288 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
289 EXPECT_ANY_THROW(kernel.configure());
292 TEST_F(LessEqualTest, Input_Output_Type_NEG)
294 Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
295 Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
296 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
298 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
299 EXPECT_ANY_THROW(kernel.configure());
302 TEST_F(LessEqualTest, Float_Broadcast_NEG)
304 Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({2}, {1.f, 2.f}, _memory_manager.get());
305 Tensor y_tensor = makeInputTensor<DataType::FLOAT32>({3}, {1.f, 2.f, 3.f}, _memory_manager.get());
306 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
308 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
309 ASSERT_ANY_THROW(kernel.configure());
312 TEST_F(LessEqualTest, Int32_Broadcast_NEG)
314 Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
315 Tensor y_tensor = makeInputTensor<DataType::S32>({3}, {1, 2, 3}, _memory_manager.get());
316 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
318 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
319 ASSERT_ANY_THROW(kernel.configure());
322 TEST_F(LessEqualTest, Int64_Broadcast_NEG)
324 Tensor x_tensor = makeInputTensor<DataType::S64>({2}, {1, 2}, _memory_manager.get());
325 Tensor y_tensor = makeInputTensor<DataType::S64>({3}, {1, 2, 3}, _memory_manager.get());
326 Tensor output_tensor = makeOutputTensor(DataType::BOOL);
328 LessEqual kernel(&x_tensor, &y_tensor, &output_tensor);
329 ASSERT_ANY_THROW(kernel.configure());
333 } // namespace kernels
334 } // namespace luci_interpreter