1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
19 #include "ngraph/coordinate_transform.hpp"
20 #include "ngraph/op/quantize.hpp"
21 #include "ngraph/shape_util.hpp"
23 NGRAPH_SUPPRESS_DEPRECATED_START
31 template <typename REAL, typename QUANT>
32 void quantize(const REAL* input,
34 const QUANT* zero_point,
36 const Shape& input_shape,
37 const Shape& scale_zero_point_shape,
39 op::Quantize::RoundMode round_mode)
41 CoordinateTransform input_transform(input_shape);
42 CoordinateTransform scale_zero_point_transform(scale_zero_point_shape);
44 for (const Coordinate& input_coord : input_transform)
46 Coordinate scale_zero_point_coord = project(input_coord, axes);
49 REAL qvalue = input[input_transform.index(input_coord)] /
50 scale[scale_zero_point_transform.index(scale_zero_point_coord)];
53 if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY)
55 REAL abs_qvalue = std::fabs(qvalue);
56 REAL abs_qvalue_toward_inf =
57 std::floor(abs_qvalue + static_cast<REAL>(0.5));
58 qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_inf
59 : abs_qvalue_toward_inf;
61 else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_ZERO)
63 auto abs_qvalue = std::fabs(qvalue);
64 auto abs_qvalue_toward_zero =
65 std::ceil(abs_qvalue - static_cast<REAL>(0.5));
66 qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_zero
67 : abs_qvalue_toward_zero;
69 else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_UPWARD)
71 qvalue = std::floor(qvalue + static_cast<REAL>(0.5));
73 else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_DOWNWARD)
75 qvalue = std::ceil(qvalue - static_cast<REAL>(0.5));
77 else if (round_mode == op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN)
79 auto up_qvalue = std::floor(qvalue + static_cast<REAL>(0.5));
80 auto dn_qvalue = std::ceil(qvalue - static_cast<REAL>(0.5));
81 auto rem = std::fmod(up_qvalue, 2.0);
82 qvalue = (rem == 0.0) ? up_qvalue : dn_qvalue;
84 else if (round_mode == op::Quantize::RoundMode::ROUND_TOWARD_INFINITY)
86 auto abs_qvalue = std::fabs(qvalue);
87 auto abs_qvalue_toward_inf = std::ceil(abs_qvalue);
88 qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_inf
89 : abs_qvalue_toward_inf;
91 else if (round_mode == op::Quantize::RoundMode::ROUND_TOWARD_ZERO)
93 auto abs_qvalue = std::fabs(qvalue);
94 auto abs_qvalue_toward_zero = std::floor(abs_qvalue);
95 qvalue = (qvalue < static_cast<REAL>(0.0)) ? -abs_qvalue_toward_zero
96 : abs_qvalue_toward_zero;
98 else if (round_mode == op::Quantize::RoundMode::ROUND_UP)
100 qvalue = std::ceil(qvalue);
102 else if (round_mode == op::Quantize::RoundMode::ROUND_DOWN)
104 qvalue = std::floor(qvalue);
108 qvalue += zero_point[scale_zero_point_transform.index(scale_zero_point_coord)];
111 qvalue = std::max<REAL>(qvalue,
112 static_cast<REAL>(std::numeric_limits<QUANT>::min()));
113 qvalue = std::min<REAL>(qvalue,
114 static_cast<REAL>(std::numeric_limits<QUANT>::max()));
117 output[input_transform.index(input_coord)] = static_cast<QUANT>(qvalue);
124 NGRAPH_SUPPRESS_DEPRECATED_END