ONE - On-device Neural Engine
Loading...
Searching...
No Matches
DynamicUpdateSlice.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2022 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_DYNAMIC_UPDATE_SLICE_H__
19#define __NNFW_CKER_DYNAMIC_UPDATE_SLICE_H__
20
21#include "cker/Shape.h"
22
23#include <vector>
24
25namespace nnfw::cker
26{
27
29{
30public:
31 DynamicUpdateSlice() = default;
33
34private:
35 template <typename T>
36 void UpdateSlice(int32_t current_dim, int32_t max_dim, const std::vector<int32_t> &output_stride,
37 const std::vector<int32_t> &update_stride, const Shape &update_shape,
38 const T *update, const std::vector<int64_t> &indices_data, T *output)
39 {
40 if (current_dim == max_dim)
41 return;
42
43 if (current_dim == max_dim - 1)
44 {
45 output += indices_data[current_dim] * output_stride[current_dim];
46 memcpy(output, update, update_shape.Dims(max_dim - 1) * sizeof(T));
47 return;
48 }
49
50 output += indices_data[current_dim] * output_stride[current_dim];
51 for (int i = 0; i < update_shape.Dims(current_dim); ++i)
52 {
53 UpdateSlice(current_dim + 1, max_dim, output_stride, update_stride, update_shape, update,
54 indices_data, output);
55 output += output_stride[current_dim];
56 update += update_stride[current_dim];
57 }
58 }
59
60public:
61 template <typename T>
62 void operator()(const Shape &input_shape, const T *input_data, const Shape &update_shape,
63 const T *update_data, const std::vector<int64_t> &indices_data, T *output_data)
64 {
65 // Special case 1 : output is copy of update
66 if (input_shape == update_shape)
67 {
68 memcpy(output_data, update_data, update_shape.FlatSize() * sizeof(T));
69 return;
70 }
71
72 // Prepare update
73 if (input_data != output_data)
74 memcpy(output_data, input_data, input_shape.FlatSize() * sizeof(T));
75
76 // Special case 2: no update
77 if (update_shape.FlatSize() == 0)
78 return;
79
80 // Calculate clamped_start_indices
81 const auto input_dims = input_shape.DimensionsCount();
82 std::vector<int64_t> clamped_start_indices(input_dims, 0);
83 assert(input_dims == update_shape.DimensionsCount());
84 for (int i = 0; i < input_dims; i++)
85 {
86 clamped_start_indices[i] = std::min<int64_t>(std::max<int64_t>(0, indices_data[i]),
87 input_shape.Dims(i) - update_shape.Dims(i));
88 }
89
90 // Calculate strides
91 std::vector<int32_t> output_stride(input_dims);
92 std::vector<int32_t> update_stride(input_dims);
93 output_stride[input_dims - 1] = 1;
94 update_stride[input_dims - 1] = 1;
95 for (int i = input_dims - 2; i >= 0; --i)
96 {
97 output_stride[i] = output_stride[i + 1] * input_shape.Dims(i + 1);
98 update_stride[i] = update_stride[i + 1] * update_shape.Dims(i + 1);
99 }
100
101 UpdateSlice<T>(0, input_dims, output_stride, update_stride, update_shape, update_data,
102 clamped_start_indices, output_data);
103 }
104};
105
106} // namespace nnfw::cker
107
108#endif // __NNFW_CKER_DYNAMIC_UPDATE_SLICE_H__
void operator()(const Shape &input_shape, const T *input_data, const Shape &update_shape, const T *update_data, const std::vector< int64_t > &indices_data, T *output_data)
int32_t DimensionsCount() const
Definition Shape.h:103
int32_t Dims(int i) const
Definition Shape.h:106
int FlatSize() const
Definition Shape.h:256