Files
tensorflow--tensorflow/tensorflow/lite/delegates/flex/util.cc
T
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

311 lines
9.3 KiB
C++

/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
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 "tensorflow/lite/delegates/flex/util.h"
#include <cstdint>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_split.h"
#include "tensorflow/c/tf_datatype.h"
#include "tensorflow/core/framework/resource_handle.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow/core/platform/tstring.h"
#include "tensorflow/core/protobuf/error_codes.pb.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/string_util.h"
#include "tensorflow/lite/util.h"
namespace tflite {
namespace flex {
static constexpr char kResourceVariablePrefix[] = "tflite_resource_variable";
TfLiteStatus ConvertStatus(TfLiteContext* context, const absl::Status& status) {
if (!status.ok()) {
TF_LITE_KERNEL_LOG(context, "%s", absl::StatusMessageAsCStr(status));
return kTfLiteError;
}
return kTfLiteOk;
}
TfLiteStatus CopyShapeAndType(TfLiteContext* context,
const tensorflow::Tensor& src,
TfLiteTensor* tensor) {
tensor->type = GetTensorFlowLiteType(static_cast<TF_DataType>(src.dtype()));
if (tensor->type == kTfLiteNoType) {
TF_LITE_KERNEL_LOG(context,
"TF Lite does not support TensorFlow data type: %s",
DataTypeString(src.dtype()).c_str());
return kTfLiteError;
}
int num_dims = src.dims();
TfLiteIntArray* shape = TfLiteIntArrayCreate(num_dims);
for (int j = 0; j < num_dims; ++j) {
// We need to cast from TensorFlow's int64 to TF Lite's int32. Let's
// make sure there's no overflow.
if (src.dim_size(j) >= std::numeric_limits<int>::max()) {
TF_LITE_KERNEL_LOG(context,
"Dimension value in TensorFlow shape is larger than "
"supported by TF Lite");
TfLiteIntArrayFree(shape);
return kTfLiteError;
}
shape->data[j] = static_cast<int>(src.dim_size(j));
}
return context->ResizeTensor(context, tensor, shape);
}
TF_DataType GetTensorFlowDataType(TfLiteType type) {
switch (type) {
case kTfLiteNoType:
return TF_FLOAT;
case kTfLiteFloat32:
return TF_FLOAT;
case kTfLiteFloat16:
return TF_HALF;
case kTfLiteBFloat16:
return TF_BFLOAT16;
case kTfLiteFloat64:
return TF_DOUBLE;
case kTfLiteInt16:
return TF_INT16;
case kTfLiteUInt16:
return TF_UINT16;
case kTfLiteInt32:
return TF_INT32;
case kTfLiteUInt32:
return TF_UINT32;
case kTfLiteInt2:
// TODO(b/246806634): Tensorflow DT_INT2 type doesn't exist yet
return TF_INT8;
case kTfLiteUInt4:
// TODO(b/246806634): Tensorflow DT_UINT4 type doesn't exist yet
return TF_UINT8;
case kTfLiteInt4:
// TODO(b/246806634): Tensorflow DT_INT4 type doesn't exist yet
return TF_INT8;
case kTfLiteUInt8:
return TF_UINT8;
case kTfLiteInt8:
return TF_INT8;
case kTfLiteFloat8E4M3FN:
return TF_FLOAT8_E4M3FN;
case kTfLiteFloat8E5M2:
return TF_FLOAT8_E5M2;
case kTfLiteInt64:
return TF_INT64;
case kTfLiteUInt64:
return TF_UINT64;
case kTfLiteComplex64:
return TF_COMPLEX64;
case kTfLiteComplex128:
return TF_COMPLEX128;
case kTfLiteString:
return TF_STRING;
case kTfLiteBool:
return TF_BOOL;
case kTfLiteResource:
return TF_RESOURCE;
case kTfLiteVariant:
return TF_VARIANT;
}
}
TfLiteType GetTensorFlowLiteType(TF_DataType type) {
switch (type) {
case TF_FLOAT:
return kTfLiteFloat32;
case TF_HALF:
return kTfLiteFloat16;
case TF_BFLOAT16:
return kTfLiteBFloat16;
case TF_DOUBLE:
return kTfLiteFloat64;
case TF_INT16:
return kTfLiteInt16;
case TF_UINT16:
return kTfLiteUInt16;
case TF_INT32:
return kTfLiteInt32;
case TF_UINT32:
return kTfLiteUInt32;
case TF_UINT8:
return kTfLiteUInt8;
case TF_INT8:
return kTfLiteInt8;
case TF_INT64:
return kTfLiteInt64;
case TF_UINT64:
return kTfLiteUInt64;
case TF_COMPLEX64:
return kTfLiteComplex64;
case TF_COMPLEX128:
return kTfLiteComplex128;
case TF_STRING:
return kTfLiteString;
case TF_BOOL:
return kTfLiteBool;
case TF_RESOURCE:
return kTfLiteResource;
case TF_FLOAT8_E4M3FN:
return kTfLiteFloat8E4M3FN;
case TF_FLOAT8_E5M2:
return kTfLiteFloat8E5M2;
case TF_VARIANT:
return kTfLiteVariant;
default:
return kTfLiteNoType;
}
}
// Returns the TF data type name to be stored in the FunctionDef.
const char* TfLiteTypeToTfTypeName(TfLiteType type) {
switch (type) {
case kTfLiteNoType:
return "invalid";
case kTfLiteFloat32:
return "float";
case kTfLiteInt16:
return "int16";
case kTfLiteUInt16:
return "uint16";
case kTfLiteInt32:
return "int32";
case kTfLiteUInt32:
return "uint32";
case kTfLiteInt2:
return "int2";
case kTfLiteUInt4:
return "uint4";
case kTfLiteInt4:
return "int4";
case kTfLiteUInt8:
return "uint8";
case kTfLiteInt8:
return "int8";
case kTfLiteFloat8E4M3FN:
return "float8_e4m3fn";
case kTfLiteFloat8E5M2:
return "float8_e5m2";
case kTfLiteInt64:
return "int64";
case kTfLiteUInt64:
return "uint64";
case kTfLiteBool:
return "bool";
case kTfLiteComplex64:
return "complex64";
case kTfLiteComplex128:
return "complex128";
case kTfLiteString:
return "string";
case kTfLiteFloat16:
return "float16";
case kTfLiteBFloat16:
return "bfloat16";
case kTfLiteFloat64:
return "float64";
case kTfLiteResource:
return "resource";
case kTfLiteVariant:
return "variant";
}
return "invalid";
}
std::string TfLiteResourceIdentifier(const TfLiteTensor* tensor) {
// TODO(b/199782192): Create a util function to get Resource ID from a TF Lite
// resource tensor.
const int resource_id = tensor->data.i32[0];
return absl::StrFormat("%s:%d", kResourceVariablePrefix, resource_id);
}
bool GetTfLiteResourceTensorFromResourceHandle(
const tensorflow::ResourceHandle& resource_handle, TfLiteTensor* tensor) {
std::vector<std::string> parts = absl::StrSplit(resource_handle.name(), ':');
if (parts.size() != 2) {
return false;
}
const int kBytesRequired = sizeof(int32_t);
TfLiteTensorRealloc(kBytesRequired, tensor);
int resource_id;
if (parts[0] == kResourceVariablePrefix &&
absl::SimpleAtoi<int32_t>(parts[1], &resource_id)) {
// TODO(b/199782192): Create a util function to set the Resource ID of
// a TF Lite resource tensor.
GetTensorData<int32_t>(tensor)[0] = resource_id;
return true;
}
return false;
}
absl::StatusOr<tensorflow::Tensor> CreateTfTensorFromTfLiteTensor(
const TfLiteTensor* tflite_tensor) {
if (IsResourceOrVariant(tflite_tensor)) {
// Returns error if the input tflite tensor has variant or resource type.
return absl::Status(absl::StatusCode::kInvalidArgument,
"Input tensor has resource or variant type.");
}
tensorflow::TensorShape shape;
int num_dims = tflite_tensor->dims->size;
for (int i = 0; i < num_dims; ++i) {
shape.AddDim(tflite_tensor->dims->data[i]);
}
tensorflow::Tensor tf_tensor(
tensorflow::DataType(GetTensorFlowDataType(tflite_tensor->type)), shape);
if (tf_tensor.dtype() == tensorflow::DataType::DT_STRING &&
tf_tensor.data()) {
tensorflow::tstring* buf =
static_cast<tensorflow::tstring*>(tf_tensor.data());
for (int i = 0; i < tflite::GetStringCount(tflite_tensor); ++buf, ++i) {
auto ref = GetString(tflite_tensor, i);
buf->assign(ref.str, ref.len);
}
} else {
if (tf_tensor.tensor_data().size() != tflite_tensor->bytes) {
return absl::Status(
absl::StatusCode::kInternal,
"TfLiteTensor's size doesn't match the TF tensor's size.");
}
if (!tflite_tensor->data.raw) {
return absl::Status(absl::StatusCode::kInternal,
"TfLiteTensor's data field is null.");
}
std::memcpy(tf_tensor.data(), tflite_tensor->data.raw,
tflite_tensor->bytes);
}
return tf_tensor;
}
} // namespace flex
} // namespace tflite