ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Tile.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 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#include "kernels/Tile.h"
19
20#include "kernels/Utils.h"
21
22namespace luci_interpreter
23{
24namespace kernels
25{
26
27Tile::Tile(const Tensor *input, const Tensor *multiples, Tensor *output)
28 : Kernel({input, multiples}, {output})
29{
30}
31
33{
34 LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= 1);
35 LUCI_INTERPRETER_CHECK(multiples()->shape().num_dims() == 1);
36 LUCI_INTERPRETER_CHECK(multiples()->shape().dim(0) == input()->shape().num_dims());
37 LUCI_INTERPRETER_CHECK(multiples()->element_type() == DataType::S32);
38
39 Shape output_shape(input()->shape().num_dims());
40 const int32_t *muldata = getTensorData<int32_t>(multiples());
41 int32_t num_dim = multiples()->shape().dim(0);
42 for (int32_t dim = 0; dim < num_dim; ++dim)
43 {
44 output_shape.dim(dim) = input()->shape().dim(dim) * muldata[dim];
45 }
47}
48
49void Tile::execute() const
50{
51 switch (output()->element_type())
52 {
53 case DataType::FLOAT32:
54 evalFloat();
55 break;
56 default:
57 throw std::runtime_error("luci-intp Tile Unsupported type.");
58 }
59}
60
61namespace
62{
63
64template <typename T, typename M>
65void CopyMultipleTimes(const T *in_data, int32_t in_size, M multiplier, T *out_data)
66{
67 for (M i = 0; i < multiplier; ++i)
68 {
69 const T *in_end = in_data + in_size;
70 T *new_out_data = std::copy(in_data, in_end, out_data);
71 in_data = out_data;
72 out_data = new_out_data;
73 }
74}
75
76template <typename T, typename M>
77std::pair<int, int> TileOneDimension(const tflite::RuntimeShape &in_dimensions, const T *in_data,
78 const M *multiples, T *out_data, int dimension)
79{
80 if (in_dimensions.DimensionsCount() == 0)
81 {
82 // If input tensor is a scalar, then just copy it to output (no need to multiply).
83 *out_data = *in_data;
84 return std::make_pair(0, 0);
85 }
86
87 const int dimension_size = in_dimensions.Dims(dimension);
88 if (dimension == in_dimensions.DimensionsCount() - 1)
89 {
90 CopyMultipleTimes(in_data, dimension_size, multiples[dimension], out_data);
91 return std::make_pair(dimension_size, dimension_size * static_cast<int>(multiples[dimension]));
92 }
93
94 int total_stride_size = 0, total_tiled_stride_size = 0;
95 const T *copy_from_data = in_data;
96 T *copy_to_data = out_data;
97 for (int i = 0; i < dimension_size; ++i)
98 {
99 int stride_size = 0, tiled_stride_size = 0;
100 std::tie(stride_size, tiled_stride_size) =
101 TileOneDimension(in_dimensions, copy_from_data, multiples, copy_to_data, dimension + 1);
102 copy_from_data += stride_size;
103 copy_to_data += tiled_stride_size;
104 total_stride_size += stride_size;
105 total_tiled_stride_size += tiled_stride_size;
106 }
107 CopyMultipleTimes(out_data, total_tiled_stride_size, multiples[dimension] - 1,
108 out_data + total_tiled_stride_size);
109 return std::make_pair(total_stride_size,
110 static_cast<int>(total_tiled_stride_size * multiples[dimension]));
111}
112
113} // namespace
114
115void Tile::evalFloat() const
116{
117 TileOneDimension(getTensorShape(input()), getTensorData<float>(input()),
118 getTensorData<int32_t>(multiples()), getTensorData<float>(output()), 0);
119}
120
121} // namespace kernels
122} // namespace luci_interpreter
int32_t dim(int i) const
Definition Tensor.h:41
void resize(const Shape &new_shape)
Definition Tensor.cpp:56
const Shape & shape() const
Definition Tensor.h:107
const Tensor * multiples() const
Definition Tile.h:34
Tensor * output() const
Definition Tile.h:35
const Tensor * input() const
Definition Tile.h:33
Tile(const Tensor *input, const Tensor *multiplies, Tensor *output)
Definition Tile.cpp:27
void execute() const override
Definition Tile.cpp:49
void configure() override
Definition Tile.cpp:32
#define LUCI_INTERPRETER_CHECK(cond)
Definition Utils.h:36
const luci_interpreter::RuntimeShape output_shape
tflite::RuntimeShape getTensorShape(const Tensor *tensor)
Definition Utils.h:194
void CopyMultipleTimes(const T *in_data, int32_t in_size, M multiplier, T *out_data)
Definition Tile.h:29
std::pair< int, int > TileOneDimension(const Shape &in_dimensions, const T *in_data, const M *multipliers, T *out_data, int dimension)
Definition Tile.h:41