// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "tensorflow/lite/core/c/common.h" #include "tensorflow/lite/kernels/internal/tensor_ctypes.h" #include "tensorflow/lite/kernels/kernel_util.h" namespace tflite { namespace ops { namespace builtin { namespace sign { // Performs common preparation for pointwise, unary ops, i.e., type checks and // output tensor resizing. TfLiteStatus PointwiseUnaryOpPrepare(TfLiteContext* context, TfLiteNode* node) { TF_LITE_ENSURE_EQ(context, tflite::NumInputs(node), 1); const TfLiteTensor* input = tflite::GetInput(context, node, 0); TfLiteTensor* output = tflite::GetOutput(context, node, 0); // Validate size and type constraints TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type); TfLiteIntArray* output_shape = TfLiteIntArrayCopy(input->dims); return context->ResizeTensor(context, output, output_shape); } // Applies the operator Op pointwise to data of type T. template TfLiteStatus PointwiseUnaryOpDoEval( const TfLiteTensor* input, TfLiteTensor* output) { const T* data = tflite::GetTensorData(input); T* data_output = tflite::GetTensorData(output); const int64_t num_elements = NumElements(input); for (int64_t i = 0; i < num_elements; ++i) { data_output[i] = Op::template Eval(data[i]); } return TfLiteStatus::kTfLiteOk; } // A generic evaluation function where the actual data processing is handled // by the Op::Eval function. template TfLiteStatus PointwiseUnaryOpEval(TfLiteContext* context, TfLiteNode* node) { const TfLiteTensor* input = tflite::GetInput(context, node, 0); TfLiteTensor* output = tflite::GetOutput(context, node, 0); switch (output->type) { case kTfLiteFloat32: TF_LITE_ENSURE_OK(context, (PointwiseUnaryOpDoEval(input, output))); break; case kTfLiteFloat64: TF_LITE_ENSURE_OK(context, (PointwiseUnaryOpDoEval(input, output))); break; case kTfLiteInt32: TF_LITE_ENSURE_OK(context, (PointwiseUnaryOpDoEval(input, output))); break; default: { TF_LITE_KERNEL_LOG(context, "Unsupported datatype for sign output: %s", TfLiteTypeGetName(output->type)); return TfLiteStatus::kTfLiteError; } } return TfLiteStatus::kTfLiteOk; } // Operator that computes the sign function. struct Sign { template static T Eval(T x) { if constexpr (std::is_floating_point_v) { if (std::isnan(x)) { return x; } } if (x > 0) { return 1; } if (x < 0) { return -1; } return 0; } }; } // namespace sign TfLiteRegistration* Register_SIGN() { static TfLiteRegistration r = {nullptr, nullptr, sign::PointwiseUnaryOpPrepare, sign::PointwiseUnaryOpEval}; return &r; } } // namespace builtin } // namespace ops } // namespace tflite