Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / runtime / onert / backend / cpu / ops / QuantizeLayer.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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  */
16
17 #include "OperationUtils.h"
18 #include "QuantizeLayer.h"
19
20 #include <cker/operation/Dequantize.h>
21 #include <cker/operation/Erf.h>
22 #include <cker/operation/Exp.h>
23 #include <cker/operation/LogicalNot.h>
24 #include <cker/operation/Quantize.h>
25 #include <cker/operation/Round.h>
26
27 namespace onert
28 {
29 namespace backend
30 {
31 namespace cpu
32 {
33 namespace ops
34 {
35 template <typename InputT, typename OutputT>
36 void affineQuantize(const IPortableTensor *input, IPortableTensor *output)
37 {
38   nnfw::cker::Quantize(getShape(input), getBuffer<InputT>(input), getShape(output),
39                        getBuffer<OutputT>(output), output->data_scale(), output->data_zero_point());
40 }
41
42 void QuantizeLayer::configure(const IPortableTensor *input, IPortableTensor *output)
43 {
44   assert(input != nullptr);
45   assert(output != nullptr);
46
47   _input = input;
48   _output = output;
49
50   if ((_input->data_type() == OperandType::FLOAT32))
51   {
52     // DO NOTHING
53   }
54   else if (((input->data_type() == OperandType::QUANT_UINT8_ASYMM) &&
55             (output->data_type() == OperandType::QUANT_INT8_ASYMM)) ||
56            ((input->data_type() == OperandType::QUANT_INT8_ASYMM) &&
57             (output->data_type() == OperandType::QUANT_UINT8_ASYMM)))
58   {
59     const double effective_output_scale =
60       static_cast<double>(input->data_scale()) / static_cast<double>(output->data_scale());
61     QuantizeMultiplier(effective_output_scale, &_output_multiplier, &_output_shift);
62   }
63   else
64   {
65     throw std::runtime_error{"Quantize: Unsupported  data type"};
66   }
67 }
68
69 void QuantizeLayer::run()
70 {
71   if ((_input->data_type() == OperandType::FLOAT32))
72   {
73     affineQuantize<float, uint8_t>(_input, _output);
74   }
75   else if ((_input->data_type() == OperandType::QUANT_UINT8_ASYMM) &&
76            (_output->data_type() == OperandType::QUANT_INT8_ASYMM))
77   {
78     nnfw::cker::Requantize<uint8_t, int8_t>(
79       getBuffer<uint8_t>(_input), MatchingFlatSize(getShape(_input), getShape(_output)),
80       _output_multiplier, _output_shift, _input->data_zero_point(), _output->data_zero_point(),
81       getBuffer<int8_t>(_output));
82   }
83   else if ((_input->data_type() == OperandType::QUANT_INT8_ASYMM) &&
84            (_output->data_type() == OperandType::QUANT_UINT8_ASYMM))
85   {
86     nnfw::cker::Requantize<int8_t, uint8_t>(
87       getBuffer<int8_t>(_input), MatchingFlatSize(getShape(_input), getShape(_output)),
88       _output_multiplier, _output_shift, _input->data_zero_point(), _output->data_zero_point(),
89       getBuffer<uint8_t>(_output));
90   }
91   else
92   {
93     throw std::runtime_error{"Quantize: Unsupported  data type"};
94   }
95 }
96
97 } // namespace ops
98 } // namespace cpu
99 } // namespace backend
100 } // namespace onert