1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lrn_builder.h"
17
18 #include "mindir.h"
19 #include "ops_registry.h"
20
21 namespace OHOS {
22 namespace NeuralNetworkRuntime {
23 namespace Ops {
24 static const int INPUT_NUM = 1;
25 static const int OUTPUT_NUM = 1;
26 static const int PARAM_MAX_NUM = 5;
27 static const int SCALAR_LENGTH = 1;
28 static const std::string OP_NAME = "LRN";
29 static const std::unordered_map<int, std::string> normRegionList = {{0, "ACROSS_CHANNELS"}};
30
LRNBuilder()31 LRNBuilder::LRNBuilder() {}
32
~LRNBuilder()33 LRNBuilder::~LRNBuilder() {}
34
SetDepthRadius(const std::shared_ptr<NNTensor> & tensor)35 OH_NN_ReturnCode LRNBuilder::SetDepthRadius(const std::shared_ptr<NNTensor>& tensor)
36 {
37 if (tensor->GetDataType() != OH_NN_INT64) {
38 LOGE("[LRN] The depthRadius should be type OH_NN_INT64.");
39 return OH_NN_INVALID_PARAMETER;
40 }
41
42 if (tensor->GetElementCount() != SCALAR_LENGTH) {
43 LOGE("[LRN] The depthRadius should be scalar.");
44 return OH_NN_INVALID_PARAMETER;
45 }
46
47 void* buffer = tensor->GetBuffer();
48 if (buffer == nullptr) {
49 LOGE("[LRN] Tensor buffer is nullptr.");
50 return OH_NN_INVALID_PARAMETER;
51 }
52 m_depthRadius = *(static_cast<const int64_t*>(buffer));
53
54 return OH_NN_SUCCESS;
55 }
56
SetBias(const std::shared_ptr<NNTensor> & tensor)57 OH_NN_ReturnCode LRNBuilder::SetBias(const std::shared_ptr<NNTensor>& tensor)
58 {
59 if (tensor->GetDataType() != OH_NN_FLOAT32) {
60 LOGE("[LRN] The bias should be type OH_NN_FLOAT32.");
61 return OH_NN_INVALID_PARAMETER;
62 }
63
64 if (tensor->GetElementCount() != SCALAR_LENGTH) {
65 LOGE("[LRN] The bias should be scalar.");
66 return OH_NN_INVALID_PARAMETER;
67 }
68
69 void* buffer = tensor->GetBuffer();
70 if (buffer == nullptr) {
71 LOGE("[LRN] Tensor buffer is nullptr.");
72 return OH_NN_INVALID_PARAMETER;
73 }
74 m_bias = *(static_cast<const float*>(buffer));
75
76 return OH_NN_SUCCESS;
77 }
78
SetAlpha(const std::shared_ptr<NNTensor> & tensor)79 OH_NN_ReturnCode LRNBuilder::SetAlpha(const std::shared_ptr<NNTensor>& tensor)
80 {
81 if (tensor->GetDataType() != OH_NN_FLOAT32) {
82 LOGE("[LRN] The alpha should be type OH_NN_FLOAT32.");
83 return OH_NN_INVALID_PARAMETER;
84 }
85
86 if (tensor->GetElementCount() != SCALAR_LENGTH) {
87 LOGE("[LRN] The alpha should be scalar.");
88 return OH_NN_INVALID_PARAMETER;
89 }
90
91 void* buffer = tensor->GetBuffer();
92 if (buffer == nullptr) {
93 LOGE("[LRN] Tensor buffer is nullptr.");
94 return OH_NN_INVALID_PARAMETER;
95 }
96 m_alpha = *(static_cast<const float*>(buffer));
97
98 return OH_NN_SUCCESS;
99 }
100
SetBeta(const std::shared_ptr<NNTensor> & tensor)101 OH_NN_ReturnCode LRNBuilder::SetBeta(const std::shared_ptr<NNTensor>& tensor)
102 {
103 if (tensor->GetDataType() != OH_NN_FLOAT32) {
104 LOGE("[LRN] The beta should be type OH_NN_FLOAT32.");
105 return OH_NN_INVALID_PARAMETER;
106 }
107
108 if (tensor->GetElementCount() != SCALAR_LENGTH) {
109 LOGE("[LRN] The beta should be scalar.");
110 return OH_NN_INVALID_PARAMETER;
111 }
112
113 void* buffer = tensor->GetBuffer();
114 if (buffer == nullptr) {
115 LOGE("[LRN] Tensor buffer is nullptr.");
116 return OH_NN_INVALID_PARAMETER;
117 }
118 m_beta = *(static_cast<const float*>(buffer));
119
120 return OH_NN_SUCCESS;
121 }
122
SetNormRegion(const std::shared_ptr<NNTensor> & tensor)123 OH_NN_ReturnCode LRNBuilder::SetNormRegion(const std::shared_ptr<NNTensor>& tensor)
124 {
125 if (tensor->GetDataType() != OH_NN_INT32) {
126 LOGE("[LRN] The normRegion should be type OH_NN_INT32.");
127 return OH_NN_INVALID_PARAMETER;
128 }
129
130 if (tensor->GetElementCount() != SCALAR_LENGTH) {
131 LOGE("[LRN] The beta should be scalar.");
132 return OH_NN_INVALID_PARAMETER;
133 }
134
135 void* buffer = tensor->GetBuffer();
136 if (buffer == nullptr) {
137 LOGE("[LRN] Tensor buffer is nullptr.");
138 return OH_NN_INVALID_PARAMETER;
139 }
140 int normRegionKey = *(static_cast<int*>(buffer));
141 auto it = normRegionList.find(normRegionKey);
142 if (it != normRegionList.end()) {
143 m_normRegion = it->second;
144 } else {
145 LOGE("[LRN] The normRegion should between [0, 0], but get %d.", normRegionKey);
146 LOGE("[LRN] normRegion value: 0-ACROSS_CHANNELS");
147 return OH_NN_INVALID_PARAMETER;
148 }
149
150 return OH_NN_SUCCESS;
151 }
152
Build(const std::vector<uint32_t> & paramsIndex,const std::vector<uint32_t> & inputsIndex,const std::vector<uint32_t> & outputsIndex,const std::vector<std::shared_ptr<NNTensor>> & allTensors)153 OH_NN_ReturnCode LRNBuilder::Build(const std::vector<uint32_t>& paramsIndex,
154 const std::vector<uint32_t>& inputsIndex,
155 const std::vector<uint32_t>& outputsIndex,
156 const std::vector<std::shared_ptr<NNTensor>>& allTensors)
157 {
158 if (m_isBuild) {
159 LOGE("[LRN] Build failed, the LRN operation has been build. cannot build again.");
160 return OH_NN_OPERATION_FORBIDDEN;
161 }
162
163 auto ret = CheckIOIndex(inputsIndex, outputsIndex, allTensors, INPUT_NUM, OUTPUT_NUM);
164 if (ret != OH_NN_SUCCESS) {
165 LOGE("[LRN] Build failed, passed invalid input or output index.");
166 return ret;
167 }
168
169 m_inputsIndex = inputsIndex;
170 m_outputsIndex = outputsIndex;
171
172 ret = CheckParamIndex(paramsIndex, allTensors, PARAM_MAX_NUM);
173 if (ret != OH_NN_SUCCESS) {
174 LOGE("[LRN] Build failed, passed invalid input or output index.");
175 return ret;
176 }
177
178 for (int i : paramsIndex) {
179 std::shared_ptr<NNTensor> tensor = allTensors[i];
180 tensor->IdentifyOpParameter();
181 if (m_paramMap.find(tensor->GetType()) != m_paramMap.end()) {
182 ret = (this->*(m_paramMap[tensor->GetType()]))(tensor);
183 } else {
184 LOGE("[LRN] Build failed, param invalid, type=%d", tensor->GetType());
185 return OH_NN_INVALID_PARAMETER;
186 }
187
188 if (ret != OH_NN_SUCCESS) {
189 LOGE("[LRN] Build failed, passed invalid param.");
190 return ret;
191 }
192 }
193
194 m_name = OP_NAME;
195 m_isBuild = true;
196 return OH_NN_SUCCESS;
197 }
198
GetPrimitive()199 LiteGraphPrimitvePtr LRNBuilder::GetPrimitive()
200 {
201 if (!m_isBuild) {
202 LOGE("[LRN] GetPrimitive failed, cannot get primitive before call build.");
203 return {nullptr, DestroyLiteGraphPrimitive};
204 }
205
206 void* primitive = mindspore::lite::MindIR_LRN_CreatePrimitive(m_depthRadius, m_bias, m_alpha,
207 m_beta, m_normRegion);
208 LiteGraphPrimitvePtr graphPrimitivePtr(primitive, DestroyLiteGraphPrimitive) ;
209 return graphPrimitivePtr;
210 }
211
212 REGISTER_OPS(LRNBuilder, OH_NN_OPS_LRN);
213 } // namespace Ops
214 } // namespace NeuralNetworkRuntime
215 } // namespace OHOS