1 /* 2 * Copyright (C) 2018 The Android Open Source Project 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 17 #define LOG_TAG "Operations" 18 19 #include "HalInterfaces.h" 20 #include "OperationResolver.h" 21 #include "OperationsUtils.h" 22 #include "Tracing.h" 23 24 #include <cmath> 25 26 namespace android { 27 namespace nn { 28 namespace neg { 29 30 constexpr char kOperationName[] = "NEG"; 31 32 constexpr uint32_t kNumInputs = 1; 33 constexpr uint32_t kInputTensor = 0; 34 35 constexpr uint32_t kNumOutputs = 1; 36 constexpr uint32_t kOutputTensor = 0; 37 38 namespace { 39 40 template <typename T> 41 inline bool compute(const T* input, const Shape& shape, T* output) { 42 const auto size = getNumberOfElements(shape); 43 for (uint32_t i = 0; i < size; ++i) { 44 output[i] = -input[i]; 45 } 46 return true; 47 } 48 49 } // namespace 50 51 bool validate(const IOperationValidationContext* context) { 52 NN_RET_CHECK_EQ(context->getNumInputs(), kNumInputs); 53 NN_RET_CHECK_EQ(context->getNumOutputs(), kNumOutputs); 54 OperandType inputType = context->getInputType(kInputTensor); 55 NN_RET_CHECK(inputType == OperandType::TENSOR_FLOAT16 || 56 inputType == OperandType::TENSOR_FLOAT32 || inputType == OperandType::TENSOR_INT32) 57 << "Unsupported tensor type for operation " << kOperationName; 58 NN_RET_CHECK(validateInputTypes(context, {inputType})); 59 NN_RET_CHECK(validateOutputTypes(context, {inputType})); 60 return validateHalVersion(context, HalVersion::V1_2); 61 } 62 63 bool prepare(IOperationExecutionContext* context) { 64 Shape input = context->getInputShape(kInputTensor); 65 Shape output = context->getOutputShape(kOutputTensor); 66 NN_RET_CHECK(SetShape(input, &output)); 67 return context->setOutputShape(kOutputTensor, output); 68 } 69 70 bool execute(IOperationExecutionContext* context) { 71 switch (context->getInputType(kInputTensor)) { 72 case OperandType::TENSOR_FLOAT16: 73 return compute(context->getInputBuffer<_Float16>(kInputTensor), 74 context->getInputShape(kInputTensor), 75 context->getOutputBuffer<_Float16>(kOutputTensor)); 76 case OperandType::TENSOR_FLOAT32: 77 return compute(context->getInputBuffer<float>(kInputTensor), 78 context->getInputShape(kInputTensor), 79 context->getOutputBuffer<float>(kOutputTensor)); 80 case OperandType::TENSOR_INT32: 81 return compute(context->getInputBuffer<int32_t>(kInputTensor), 82 context->getInputShape(kInputTensor), 83 context->getOutputBuffer<int32_t>(kOutputTensor)); 84 default: 85 NN_RET_CHECK_FAIL() << "Unsupported tensor type for operation " << kOperationName; 86 } 87 } 88 89 } // namespace neg 90 91 NN_REGISTER_OPERATION(NEG, neg::kOperationName, neg::validate, neg::prepare, neg::execute); 92 93 } // namespace nn 94 } // namespace android 95