Imported Upstream version 1.11.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->dimension(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 =
51         (_input->dimension(dim + 1) + reinterpret_cast<int32_t *>(_padding->buffer())[dim * 2] +
52          reinterpret_cast<int32_t *>(_padding->buffer())[dim * 2 + 1]);
53
54     if (final_dim_size % reinterpret_cast<int32_t *>(_block_shape->buffer())[dim] != 0)
55     {
56       throw std::runtime_error(
57           "SpaceToBatchND : padded input's dimension is not a multiple of block size\n");
58     }
59
60     if ((int32_t)_output->dimension(dim + 1) !=
61         final_dim_size / reinterpret_cast<int32_t *>(_block_shape->buffer())[dim])
62     {
63       throw std::runtime_error("SpaceToBatchND : wrong output dimension\n");
64     }
65   }
66 }
67
68 template <> uint32_t SpaceToBatchNDLayer::getPad<float>() { return 0; }
69 template <> uint32_t SpaceToBatchNDLayer::getPad<uint8_t>() { return _output->data_offset(); }
70
71 template <typename T> void SpaceToBatchNDLayer::spaceToBatchND()
72 {
73   checkDimension();
74
75   nnfw::cker::SpaceToBatchParams params;
76   params.output_offset = getPad<T>();
77
78   nnfw::cker::SpaceToBatchND(
79       params, getTensorShape(_input), reinterpret_cast<const T *>(_input->buffer()),
80       getTensorShape(_block_shape), reinterpret_cast<const int32_t *>(_block_shape->buffer()),
81       getTensorShape(_padding), reinterpret_cast<const int32_t *>(_padding->buffer()),
82       getTensorShape(_output), reinterpret_cast<T *>(_output->buffer()));
83 }
84
85 void SpaceToBatchNDLayer::configure(const IPortableTensor *input,
86                                     const IPortableTensor *block_shape,
87                                     const IPortableTensor *padding, IPortableTensor *output)
88 {
89   _input = input;
90   _block_shape = block_shape;
91   _padding = padding;
92   _output = output;
93 }
94
95 void SpaceToBatchNDLayer::run()
96 {
97   if (_input->data_type() == OperandType::FLOAT32)
98   {
99     spaceToBatchND<float>();
100   }
101   else if (_input->data_type() == OperandType::QUANT_UINT8_ASYMM)
102   {
103     spaceToBatchND<uint8_t>();
104   }
105   else
106   {
107     throw std::runtime_error{"SpaceToBatchND: unsupported data type"};
108   }
109 }
110
111 } // namespace ops
112 } // namespace cpu
113 } // namespace backend
114 } // namespace onert