ONE - On-device Neural Engine
Loading...
Searching...
No Matches
CircleConcatenation.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 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
18
19#include "CircleCloneNode.h"
20
22
23namespace luci
24{
25
27{
29 return nullptr;
30
31 auto *cloned = _graph->nodes()->create<luci::CircleConcatenation>(node->numValues());
32 if (cloned != nullptr)
33 {
35 cloned->axis(node->axis());
36 }
37 return cloned;
38}
39
40namespace sinf
41{
42
44{
45 // TODO Support when CircleConcatenation has 0 input
46 assert(node->numValues() > 0);
47
48 auto first_shape = luci::shape_get(node->values(0)).as<loco::TensorShape>();
49 auto axis = node->axis();
50 if (axis < 0)
51 axis += first_shape.rank();
52
53 assert(0 <= axis);
54 assert(first_shape.rank() > static_cast<uint32_t>(axis));
55
57
58 output_shape.rank(first_shape.rank());
59 for (uint32_t i = 0; i < output_shape.rank(); ++i)
60 output_shape.dim(i) = first_shape.dim(i);
61
62 for (uint32_t i = 1; i < node->numValues(); ++i)
63 {
64 auto input_shape = luci::shape_get(node->values(i)).as<loco::TensorShape>();
65 if (input_shape.rank() != output_shape.rank())
66 INTERNAL_EXN_V("Input has incompatible shape", node->name());
67
68 for (uint32_t j = 0; j < output_shape.rank(); ++j)
69 {
70 if (j == static_cast<uint32_t>(axis))
71 {
72 if (output_shape.dim(j).known() and input_shape.dim(j).known())
73 {
74 output_shape.dim(j) = output_shape.dim(j).value() + input_shape.dim(j).value();
75 }
76 else
77 {
78 // If any of inputs is unknown, just mark it as unknown.
79 output_shape.dim(j).unset();
80 }
81 }
82 else
83 {
84 if (output_shape.dim(j).known() and input_shape.dim(j).known())
85 {
86 if (output_shape.dim(j).value() != input_shape.dim(j).value())
87 {
88 INTERNAL_EXN_V("Input has incompatible shape.", node->name());
89 }
90 }
91 else
92 {
93 if (input_shape.dim(j).known())
94 {
95 assert(not output_shape.dim(j).known()); // FIX_ME_UNLESS
96 output_shape.dim(j) = input_shape.dim(j);
97 }
98 // For unknown input_shape, leave output_shape as-is
99 }
100 }
101 }
102 }
103
104 return output_shape;
105}
106
107} // namespace sinf
108
109} // namespace luci
#define INTERNAL_EXN_V(msg, val)
@ brief throw internal exception with message and value
Definition InternalExn.h:28
ShapeType as(void) const
uint32_t rank(void) const
Definition TensorShape.h:35
CONCATENATION in Circle.
uint32_t numValues(void) const
Node * values(uint32_t index) const
loco::TensorShape visit(const luci::CircleNode *node) final
Default fallback.
const luci_interpreter::RuntimeShape output_shape
loco::NodeShape shape_get(const loco::Node *node)
NodeName name(void) const