2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #ifndef __NNFW_CKER_SPACE_TO_BATCH_ND_H__
19 #define __NNFW_CKER_SPACE_TO_BATCH_ND_H__
21 #include "cker/Shape.h"
22 #include "cker/Types.h"
30 inline void SpaceToBatchND(const SpaceToBatchParams ¶ms, 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,
36 UNUSED_RELEASE(unextended_block_shape_shape);
37 UNUSED_RELEASE(unextended_padding_shape);
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);
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);
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);
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];
58 // For uint8 quantized, the correct padding "zero value" is the output offset.
59 const int32_t pad_value = params.output_offset;
61 for (int out_b = 0; out_b < output_batch_size; ++out_b)
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)
68 for (int out_w = 0; out_w < output_width; ++out_w)
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)
76 // This may not execute correctly when pad_value != 0 and T != uint8.
77 memset(out, pad_value, depth * sizeof(T));
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));
95 #endif // __NNFW_CKER_SPACE_TO_BATCH_ND_H__