2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <NeuralNetworks.h>
18 #include <NeuralNetworksEx.h>
22 #include "wrapper/ANeuralNetworksModel.h"
23 #include "wrapper/ANeuralNetworksMemory.h"
24 #include "util/logging.h"
26 int ANeuralNetworksModel_create(ANeuralNetworksModel **model)
30 VERBOSE(NNAPI::Model) << "create: Incorrect null pointer parameter" << std::endl;
31 return ANEURALNETWORKS_UNEXPECTED_NULL;
34 *model = new (std::nothrow) ANeuralNetworksModel{};
35 if (*model == nullptr)
37 VERBOSE(NNAPI::Model) << "create: Fail to create model object" << std::endl;
38 return ANEURALNETWORKS_OUT_OF_MEMORY;
41 return ANEURALNETWORKS_NO_ERROR;
44 void ANeuralNetworksModel_free(ANeuralNetworksModel *model) { delete model; }
46 int ANeuralNetworksModel_addOperand(ANeuralNetworksModel *model,
47 const ANeuralNetworksOperandType *type)
49 if ((model == nullptr) || (type == nullptr))
51 VERBOSE(NNAPI::Model) << "addOperand: Incorrect null pointer parameter(s)" << std::endl;
52 return ANEURALNETWORKS_UNEXPECTED_NULL;
55 if (model->isFinished())
57 VERBOSE(NNAPI::Model) << "addOperand: Already finished" << std::endl;
58 return ANEURALNETWORKS_BAD_STATE;
61 // scale and zeroPoint should be zero for scalars and non-fixed point tensors
63 // scale: a 32 bit floating point value greater than zero
64 // zeroPoint: a 32 bit integer, in range [0, 255]
65 if (type->type == ANEURALNETWORKS_TENSOR_QUANT8_ASYMM)
67 if (!(type->scale > 0.0f))
69 VERBOSE(NNAPI::Model) << "addOperand: Incorrect scale value for quantization" << std::endl;
70 return ANEURALNETWORKS_BAD_DATA;
73 if ((type->zeroPoint < 0) || (type->zeroPoint > 255))
75 VERBOSE(NNAPI::Model) << "addOperand: Incorrect zeroPoint value for quantization"
77 return ANEURALNETWORKS_BAD_DATA;
80 // NOTE Validation of scale and zeroPoint would be skipped for a while.
81 // We do not know whether scalar type can have scale and zeroPoint.
82 // To pass ValidationTest and GeneratedTest, this validation code
83 // would not be implemented until we can define this issue clearly.
85 // scale and zeroPoint should be zero for scalars and non-fixed point tensors
86 // else if ((type->scale != 0.0f) || (type->zeroPoint != 0))
88 // return ANEURALNETWORKS_BAD_DATA;
91 // dimensionCount should be zero for scalars
92 if ((type->dimensionCount != 0) &&
93 ((type->type == ANEURALNETWORKS_FLOAT32) || (type->type == ANEURALNETWORKS_INT32) ||
94 (type->type == ANEURALNETWORKS_UINT32)))
96 VERBOSE(NNAPI::Model) << "addOperand: Incorrect data type" << std::endl;
97 return ANEURALNETWORKS_BAD_DATA;
100 if (!model->addOperand(type))
102 VERBOSE(NNAPI::Model) << "addOperand: Fail to add operand" << std::endl;
103 return ANEURALNETWORKS_BAD_DATA;
106 return ANEURALNETWORKS_NO_ERROR;
109 int ANeuralNetworksModel_setOperandValue(ANeuralNetworksModel *model, int32_t index,
110 const void *buffer, size_t length)
112 const bool optional_operand = ((buffer == nullptr) && (length == 0));
114 if ((model == nullptr) || ((buffer == nullptr) && (length != 0)))
116 VERBOSE(NNAPI::Model) << "setOperandValue: Incorrect null pointer parameter(s)" << std::endl;
117 return ANEURALNETWORKS_UNEXPECTED_NULL;
120 if (model->isFinished())
122 VERBOSE(NNAPI::Model) << "setOperandValue: Already finished" << std::endl;
123 return ANEURALNETWORKS_BAD_STATE;
126 // Negative index value is not allowed
129 VERBOSE(NNAPI::Model) << "setOperandValue: Invalid index value (negative)" << std::endl;
130 return ANEURALNETWORKS_BAD_DATA;
132 // NOTE OperandIndex uses uint32_t as its underlying type as various NNAPI
133 // functions such as ANeuralNetworksModel_addOperation use uint32_t to represent operand
135 // ANeuralNetworksModel_setOperandValue, however, uses int32_t to represent operand index.
137 // Below, static_cast<uint32_t>(...) is introduced to eliminate compiler warning.
138 uint32_t ind = static_cast<uint32_t>(index);
140 if (!model->isExistOperand(ind))
142 VERBOSE(NNAPI::Model) << "setOperandValue: Invalid index value (not exist)" << std::endl;
143 return ANEURALNETWORKS_BAD_DATA;
146 if (!optional_operand && (model->operandSize(ind) != length))
148 VERBOSE(NNAPI::Model) << "setOperandValue: Invalid data length" << std::endl;
149 return ANEURALNETWORKS_BAD_DATA;
152 if (model->isUsageSet(ind))
154 VERBOSE(NNAPI::Model) << "setOperandValue: Already set operand" << std::endl;
155 return ANEURALNETWORKS_BAD_DATA;
158 // NNAPI spec in NeuralNetworks.h
159 // For values of length greater than ANEURALNETWORKS_MAX_SIZE_OF_IMMEDIATELY_COPIED_VALUES,
160 // the application is responsible for not changing the content of this region
161 // until all executions using this model have completed
162 bool copy_value = false;
163 if (length <= ANEURALNETWORKS_MAX_SIZE_OF_IMMEDIATELY_COPIED_VALUES)
168 if (!model->setOperandValue(ind, buffer, length, optional_operand, copy_value))
170 VERBOSE(NNAPI::Model) << "setOperandValue: Fail to set operand value" << std::endl;
171 return ANEURALNETWORKS_BAD_DATA;
174 return ANEURALNETWORKS_NO_ERROR;
177 int ANeuralNetworksModel_setOperandValueFromMemory(ANeuralNetworksModel *model, int32_t index,
178 const ANeuralNetworksMemory *memory,
179 size_t offset, size_t length)
181 if ((model == nullptr) || (memory == nullptr))
183 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Incorrect null pointer parameter(s)"
185 return ANEURALNETWORKS_UNEXPECTED_NULL;
188 if (model->isFinished())
190 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Already finished" << std::endl;
191 return ANEURALNETWORKS_BAD_STATE;
194 // Negative index value is not allowed
197 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Invalid index value (negative)"
199 return ANEURALNETWORKS_BAD_DATA;
201 // NOTE OperandIndex uses uint32_t as its underlying type as various NNAPI
202 // functions such as ANeuralNetworksModel_addOperation use uint32_t to represent operand
204 // ANeuralNetworksModel_setOperandValue, however, uses int32_t to represent operand index.
206 // Below, static_cast<uint32_t>(...) is introduced to eliminate compiler warning.
207 uint32_t ind = static_cast<uint32_t>(index);
209 if (!model->isExistOperand(ind))
211 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Invalid index value (not exist)"
213 return ANEURALNETWORKS_BAD_DATA;
216 if ((model->operandSize(ind) != length) || (memory->size() < (offset + length)))
218 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Invalid data length" << std::endl;
219 return ANEURALNETWORKS_BAD_DATA;
222 if (model->isUsageSet(ind))
224 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Already set operand" << std::endl;
225 return ANEURALNETWORKS_BAD_DATA;
228 if (!model->setOperandValue(ind, memory->base() + offset, length))
230 VERBOSE(NNAPI::Model) << "setOperandValueFromMemory: Fail to set operand value" << std::endl;
231 return ANEURALNETWORKS_BAD_DATA;
234 return ANEURALNETWORKS_NO_ERROR;
237 int ANeuralNetworksModel_addOperation(ANeuralNetworksModel *model,
238 ANeuralNetworksOperationType type, uint32_t inputCount,
239 const uint32_t *inputs, uint32_t outputCount,
240 const uint32_t *outputs)
242 if ((model == nullptr) || (inputs == nullptr) || (outputs == nullptr))
244 VERBOSE(NNAPI::Model) << "addOperation: Incorrect null pointer parameter(s)" << std::endl;
245 return ANEURALNETWORKS_UNEXPECTED_NULL;
248 if (model->isFinished())
250 VERBOSE(NNAPI::Model) << "addOperation: Already finished" << std::endl;
251 return ANEURALNETWORKS_BAD_STATE;
254 const ANeuralNetworksOperationType FIRST_OPERATION = ANEURALNETWORKS_ADD;
255 const ANeuralNetworksOperationType LAST_OPERATION = ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR;
256 if ((type < FIRST_OPERATION) || (type > LAST_OPERATION))
258 return ANEURALNETWORKS_BAD_DATA;
261 for (uint32_t i = 0; i < outputCount; i++)
263 if (model->isUsageSet(outputs[i]))
265 VERBOSE(NNAPI::Model) << "addOperation: Already set output operand" << std::endl;
266 return ANEURALNETWORKS_BAD_DATA;
270 if (!model->addOperation(type, inputCount, inputs, outputCount, outputs))
272 VERBOSE(NNAPI::Model) << "addOperation: Fail to add operation" << std::endl;
273 return ANEURALNETWORKS_BAD_DATA;
276 return ANEURALNETWORKS_NO_ERROR;
279 int ANeuralNetworksModel_addOperationEx(ANeuralNetworksModel *model,
280 ANeuralNetworksOperationTypeEx type, uint32_t inputCount,
281 const uint32_t *inputs, uint32_t outputCount,
282 const uint32_t *outputs)
284 if ((model == nullptr) || (inputs == nullptr) || (outputs == nullptr))
286 VERBOSE(NNAPI::Model) << "addOperation: Incorrect null pointer parameter(s)" << std::endl;
287 return ANEURALNETWORKS_UNEXPECTED_NULL;
290 if (model->isFinished())
292 VERBOSE(NNAPI::Model) << "addOperation: Already finished" << std::endl;
293 return ANEURALNETWORKS_BAD_STATE;
296 const ANeuralNetworksOperationTypeEx FIRST_OPERATION = ANEURALNETWORKS_CAST_EX;
297 const ANeuralNetworksOperationTypeEx LAST_OPERATION = ANEURALNETWORKS_ADDV2_EX;
298 if ((type < FIRST_OPERATION) || (type > LAST_OPERATION))
300 VERBOSE(NNAPI::Model) << "addOperation: Invalid operation type" << std::endl;
301 return ANEURALNETWORKS_BAD_DATA;
304 for (uint32_t i = 0; i < outputCount; i++)
306 if (model->isUsageSet(outputs[i]))
308 VERBOSE(NNAPI::Model) << "addOperation: Already set output operand" << std::endl;
309 return ANEURALNETWORKS_BAD_DATA;
313 if (!model->addOperationEx(type, inputCount, inputs, outputCount, outputs))
315 VERBOSE(NNAPI::Model) << "addOperation: Fail to add operation" << std::endl;
316 return ANEURALNETWORKS_BAD_DATA;
319 return ANEURALNETWORKS_NO_ERROR;
322 int ANeuralNetworksModel_identifyInputsAndOutputs(ANeuralNetworksModel *model, uint32_t inputCount,
323 const uint32_t *inputs, uint32_t outputCount,
324 const uint32_t *outputs)
326 if ((model == nullptr) || (inputs == nullptr) || (outputs == nullptr))
328 VERBOSE(NNAPI::Model) << "identifyInputsAndOutputs: Incorrect null pointer parameter(s)"
330 return ANEURALNETWORKS_UNEXPECTED_NULL;
333 if (model->isFinished())
335 VERBOSE(NNAPI::Model) << "identifyInputsAndOutputs: Already finished" << std::endl;
336 return ANEURALNETWORKS_BAD_STATE;
339 for (uint32_t n = 0; n < inputCount; ++n)
341 uint32_t ind = inputs[n];
342 if (model->isUsageSet(ind))
344 VERBOSE(NNAPI::Model) << "identifyInputsAndOutputs: Already set input operand" << std::endl;
345 return ANEURALNETWORKS_BAD_DATA;
348 if (!model->addModelInput(ind))
350 VERBOSE(NNAPI::Model) << "identifyInputsAndOutputs: Fail to add input" << std::endl;
351 return ANEURALNETWORKS_BAD_DATA;
355 for (uint32_t n = 0; n < outputCount; ++n)
357 uint32_t ind = outputs[n];
359 if (!model->isOperationOutput(ind))
361 VERBOSE(NNAPI::Model) << "identifyInputsAndOutputs: Need to set output operand" << std::endl;
362 return ANEURALNETWORKS_BAD_DATA;
365 if (!model->addModelOutput(ind))
367 VERBOSE(NNAPI::Model) << "identifyInputsAndOutputs: Fail to add output" << std::endl;
368 return ANEURALNETWORKS_BAD_DATA;
372 return ANEURALNETWORKS_NO_ERROR;
375 int ANeuralNetworksModel_finish(ANeuralNetworksModel *model)
377 if (model == nullptr)
379 VERBOSE(NNAPI::Model) << "finish: Incorrect null pointer parameter" << std::endl;
380 return ANEURALNETWORKS_UNEXPECTED_NULL;
383 if (model->isFinished())
385 VERBOSE(NNAPI::Model) << "finish: Already finished" << std::endl;
386 return ANEURALNETWORKS_BAD_STATE;
389 if (!model->finish())
391 VERBOSE(NNAPI::Model) << "finish: Fail to generate internal graph" << std::endl;
392 return ANEURALNETWORKS_BAD_STATE;
395 return ANEURALNETWORKS_NO_ERROR;
398 int ANeuralNetworksModel_relaxComputationFloat32toFloat16(ANeuralNetworksModel *model, bool allow)
400 if (model == nullptr)
402 VERBOSE(NNAPI::Model) << "relaxComputationFloat32toFloat16: Incorrect null pointer parameter"
404 return ANEURALNETWORKS_UNEXPECTED_NULL;
407 if (model->isFinished())
409 VERBOSE(NNAPI::Model) << "relaxComputationFloat32toFloat16: Already finished" << std::endl;
410 return ANEURALNETWORKS_BAD_STATE;
413 model->allowFloat32toFloat16(allow);
415 return ANEURALNETWORKS_NO_ERROR;