feeb358c9d08ea91490bfa4ce06bf97522402239
[platform/core/ml/nnfw.git] / compute / cker / include / cker / operation / SpaceToBatchND.h
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #ifndef __NNFW_CKER_SPACE_TO_BATCH_ND_H__
19 #define __NNFW_CKER_SPACE_TO_BATCH_ND_H__
20
21 #include "cker/Shape.h"
22 #include "cker/Types.h"
23
24 namespace nnfw
25 {
26 namespace cker
27 {
28
29 template <typename T>
30 inline void SpaceToBatchND(const SpaceToBatchParams &params, const Shape &unextended_input_shape,
31                            const T *input_data, const Shape &unextended_block_shape_shape,
32                            const int32_t *block_shape_data, const Shape &unextended_padding_shape,
33                            const int32_t *paddings_data, const Shape &unextended_output_shape,
34                            T *output_data)
35 {
36   UNUSED_RELEASE(unextended_block_shape_shape);
37   UNUSED_RELEASE(unextended_padding_shape);
38
39   assert(unextended_input_shape.DimensionsCount() <= 4);
40   assert(unextended_output_shape.DimensionsCount() <= 4);
41   const Shape input_shape = Shape::ExtendedShape(4, unextended_input_shape);
42   const Shape output_shape = Shape::ExtendedShape(4, unextended_output_shape);
43
44   const int depth = input_shape.Dims(3);
45   const int input_width = input_shape.Dims(2);
46   const int input_height = input_shape.Dims(1);
47   const int input_batch_size = input_shape.Dims(0);
48
49   const int output_width = output_shape.Dims(2);
50   const int output_height = output_shape.Dims(1);
51   const int output_batch_size = output_shape.Dims(0);
52
53   const int block_shape_height = block_shape_data[0];
54   const int block_shape_width = block_shape_data[1];
55   const int padding_top = paddings_data[0];
56   const int padding_left = paddings_data[2];
57
58   // For uint8 quantized, the correct padding "zero value" is the output offset.
59   const int32_t pad_value = params.output_offset;
60
61   for (int out_b = 0; out_b < output_batch_size; ++out_b)
62   {
63     int input_batch = out_b % input_batch_size;
64     int shift_w = (out_b / input_batch_size) % block_shape_width;
65     int shift_h = (out_b / input_batch_size) / block_shape_width;
66     for (int out_h = 0; out_h < output_height; ++out_h)
67     {
68       for (int out_w = 0; out_w < output_width; ++out_w)
69       {
70         T *out = output_data + Offset(output_shape, out_b, out_h, out_w, 0);
71         if (out_h * block_shape_height + shift_h < padding_top ||
72             out_h * block_shape_height + shift_h >= padding_top + input_height ||
73             out_w * block_shape_width + shift_w < padding_left ||
74             out_w * block_shape_width + shift_w >= padding_left + input_width)
75         {
76           // This may not execute correctly when pad_value != 0 and T != uint8.
77           memset(out, pad_value, depth * sizeof(T));
78         }
79         else
80         {
81           const T *in =
82               input_data + Offset(input_shape, input_batch,
83                                   (out_h * block_shape_height + shift_h) - padding_top,
84                                   (out_w * block_shape_width + shift_w) - padding_left, 0);
85           memcpy(out, in, depth * sizeof(T));
86         }
87       }
88     }
89   }
90 }
91
92 } // namespace cker
93 } // namespace nnfw
94
95 #endif // __NNFW_CKER_SPACE_TO_BATCH_ND_H__