diff options
Diffstat (limited to 'compiler/luci-interpreter/src/kernels/TestUtils.h')
-rw-r--r-- | compiler/luci-interpreter/src/kernels/TestUtils.h | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/compiler/luci-interpreter/src/kernels/TestUtils.h b/compiler/luci-interpreter/src/kernels/TestUtils.h deleted file mode 100644 index e5bd6a2db..000000000 --- a/compiler/luci-interpreter/src/kernels/TestUtils.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved - * Copyright 2017 The TensorFlow Authors. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LUCI_INTERPRETER_KERNELS_TESTUTILS_H -#define LUCI_INTERPRETER_KERNELS_TESTUTILS_H - -#include "luci_interpreter/core/Tensor.h" - -#include <type_traits> - -#include <gtest/gtest.h> -#include <gmock/gmock.h> - -namespace luci_interpreter -{ -namespace kernels -{ -namespace testing -{ - -template <typename T> -std::vector<T> quantize(const std::vector<float> &data, float scale, int32_t zero_point); - -template <DataType DT> -Tensor makeInputTensor(const Shape &shape, const std::vector<typename DataTypeImpl<DT>::Type> &data) -{ - Tensor tensor(DT, shape, {}, ""); - tensor.writeData(data.data(), data.size() * sizeof(typename DataTypeImpl<DT>::Type)); - return tensor; -} - -template <DataType DT> -Tensor makeInputTensor(const Shape &shape, float scale, int32_t zero_point, - const std::vector<float> &data) -{ - using NativeT = typename DataTypeImpl<DT>::Type; - Tensor tensor(DT, shape, {{scale}, {zero_point}}, ""); - std::vector<NativeT> quantized_data = quantize<NativeT>(data, scale, zero_point); - tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(NativeT)); - return tensor; -} - -Tensor makeOutputTensor(DataType element_type); -Tensor makeOutputTensor(DataType element_type, float scale, int32_t zero_point); - -std::vector<int32_t> extractTensorShape(const Tensor &tensor); - -// Returns the corresponding DataType given the type T. -template <typename T> constexpr DataType getElementType() -{ - if (std::is_same<T, float>::value) - return DataType::FLOAT32; - if (std::is_same<T, uint8_t>::value) - return DataType::U8; - if (std::is_same<T, int32_t>::value) - return DataType::S32; - if (std::is_same<T, int64_t>::value) - return DataType::S64; - return DataType::Unknown; -} - -template <typename T> std::vector<T> extractTensorData(const Tensor &tensor) -{ - const auto *data_ptr = tensor.data<T>(); - return std::vector<T>(data_ptr, data_ptr + tensor.shape().num_elements()); -} - -std::vector<float> dequantizeTensorData(const Tensor &tensor); - -// Array version of `::testing::FloatNear` matcher. -::testing::Matcher<std::vector<float>> FloatArrayNear(const std::vector<float> &values, - float max_abs_error = 1.0e-5f); - -template <typename T> -std::vector<T> quantize(const std::vector<float> &data, float scale, int32_t zero_point) -{ - static_assert(std::is_integral<T>::value, "Integral type expected."); - - float q_min{}, q_max{}; - if (std::is_signed<T>::value) - { - // For now, assume that signed type implies signed symmetric quantization. - assert(zero_point == 0); - q_min = -std::numeric_limits<T>::max(); - q_max = std::numeric_limits<T>::max(); - } - else - { - q_min = 0; - q_max = std::numeric_limits<T>::max(); - } - - std::vector<T> q; - for (const auto &f : data) - { - q.push_back(static_cast<T>( - std::max<float>(q_min, std::min<float>(q_max, std::round(zero_point + (f / scale)))))); - } - return q; -} - -template <typename T> -std::vector<float> dequantize(const std::vector<T> &data, float scale, int32_t zero_point) -{ - static_assert(std::is_integral<T>::value, "Integral type expected."); - std::vector<float> f; - for (const T &q : data) - { - f.push_back(scale * (q - zero_point)); - } - return f; -} - -// NOTE Returns scale and zero point for _asymmetric_ range (both signed and unsigned). -template <typename T> std::pair<float, int32_t> quantizationParams(float f_min, float f_max) -{ - static_assert(std::is_integral<T>::value, "Integral type expected."); - int32_t zero_point = 0; - float scale = 0; - const T qmin = std::numeric_limits<T>::lowest(); - const T qmax = std::numeric_limits<T>::max(); - const float qmin_double = qmin; - const float qmax_double = qmax; - // 0 should always be a representable value. Let's assume that the initial - // min,max range contains 0. - assert(f_max >= 0); - assert(f_min <= 0); - if (f_min == f_max) - { - // Special case where the min,max range is a point. Should be {0}. - assert(f_max == 0); - assert(f_min == 0); - return {scale, zero_point}; - } - - // General case. - // - // First determine the scale. - scale = (f_max - f_min) / (qmax_double - qmin_double); - - // Zero-point computation. - // First the initial floating-point computation. The zero-point can be - // determined from solving an affine equation for any known pair - // (real value, corresponding quantized value). - // We know two such pairs: (rmin, qmin) and (rmax, qmax). - // The arithmetic error on the zero point computed from either pair - // will be roughly machine_epsilon * (sum of absolute values of terms) - // so we want to use the variant that adds the smaller terms. - const float zero_point_from_min = qmin_double - f_min / scale; - const float zero_point_from_max = qmax_double - f_max / scale; - - const float zero_point_from_min_error = std::abs(qmin_double) + std::abs(f_min / scale); - - const float zero_point_from_max_error = std::abs(qmax_double) + std::abs(f_max / scale); - - const float zero_point_double = zero_point_from_min_error < zero_point_from_max_error - ? zero_point_from_min - : zero_point_from_max; - - // Now we need to nudge the zero point to be an integer - // (our zero points are integer, and this is motivated by the requirement - // to be able to represent the real value "0" exactly as a quantized value, - // which is required in multiple places, for example in Im2col with SAME - // padding). - - T nudged_zero_point = 0; - if (zero_point_double < qmin_double) - { - nudged_zero_point = qmin; - } - else if (zero_point_double > qmax_double) - { - nudged_zero_point = qmax; - } - else - { - nudged_zero_point = static_cast<T>(std::round(zero_point_double)); - } - - // The zero point should always be in the range of quantized value, - // // [qmin, qmax]. - assert(qmax >= nudged_zero_point); - assert(qmin <= nudged_zero_point); - zero_point = nudged_zero_point; - // finally, return the values - return {scale, zero_point}; -} - -inline float getTolerance(float min, float max, int quantize_steps) -{ - return ((max - min) / quantize_steps); -} - -} // namespace testing -} // namespace kernels -} // namespace luci_interpreter - -#endif // LUCI_INTERPRETER_KERNELS_TESTUTILS_H |