Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / runtime / onert / backend / cpu / ops / SpaceToBatchNDLayer.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 "SpaceToBatchNDLayer.h"
18
19 #include "OperationUtils.h"
20
21 #include <cker/operation/SpaceToBatchND.h>
22
23 namespace onert
24 {
25 namespace backend
26 {
27 namespace cpu
28 {
29 namespace ops
30 {
31 SpaceToBatchNDLayer::SpaceToBatchNDLayer()
32   : _input(nullptr), _block_shape(nullptr), _padding(nullptr), _output(nullptr)
33 {
34   // DO NOTHING
35 }
36
37 // TO DO : move into shape inferer
38 void SpaceToBatchNDLayer::checkDimension()
39 {
40   const int kSpatialDimensionNum = 2;
41   if (_block_shape->getShape().dim(0) != kSpatialDimensionNum)
42   {
43     throw std::runtime_error("SpaceToBatchND : block_shape(block_size) tensor's rank is wrong\n");
44   }
45
46   // Ensures the input height and width (with padding) is a multiple of block
47   // shape height and width.
48   for (int dim = 0; dim < kSpatialDimensionNum; ++dim)
49   {
50     int final_dim_size = (_input->getShape().dim(dim + 1) + getBuffer<int32_t>(_padding)[dim * 2] +
51                           getBuffer<int32_t>(_padding)[dim * 2 + 1]);
52
53     if (final_dim_size % getBuffer<int32_t>(_block_shape)[dim] != 0)
54     {
55       throw std::runtime_error(
56         "SpaceToBatchND : padded input's dimension is not a multiple of block size\n");
57     }
58
59     if ((int32_t)_output->getShape().dim(dim + 1) !=
60         final_dim_size / getBuffer<int32_t>(_block_shape)[dim])
61     {
62       throw std::runtime_error("SpaceToBatchND : wrong output dimension\n");
63     }
64   }
65 }
66
67 template <> uint32_t SpaceToBatchNDLayer::getPad<float>() { return 0; }
68 template <> uint32_t SpaceToBatchNDLayer::getPad<uint8_t>() { return _output->data_zero_point(); }
69
70 template <typename T> void SpaceToBatchNDLayer::spaceToBatchND()
71 {
72   checkDimension();
73
74   nnfw::cker::SpaceToBatchParams params;
75   params.output_offset = getPad<T>();
76
77   nnfw::cker::SpaceToBatchND(params, getShape(_input), getBuffer<T>(_input), getShape(_block_shape),
78                              getBuffer<int32_t>(_block_shape), getShape(_padding),
79                              getBuffer<int32_t>(_padding), getShape(_output),
80                              getBuffer<T>(_output));
81 }
82
83 void SpaceToBatchNDLayer::configure(const IPortableTensor *input,
84                                     const IPortableTensor *block_shape,
85                                     const IPortableTensor *padding, IPortableTensor *output)
86 {
87   _input = input;
88   _block_shape = block_shape;
89   _padding = padding;
90   _output = output;
91 }
92
93 void SpaceToBatchNDLayer::run()
94 {
95   if (_input->data_type() == OperandType::FLOAT32)
96   {
97     spaceToBatchND<float>();
98   }
99   else if (_input->data_type() == OperandType::QUANT_UINT8_ASYMM)
100   {
101     spaceToBatchND<uint8_t>();
102   }
103   else
104   {
105     throw std::runtime_error{"SpaceToBatchND: unsupported data type"};
106   }
107 }
108
109 } // namespace ops
110 } // namespace cpu
111 } // namespace backend
112 } // namespace onert