|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "edge-impulse-sdk/tensorflow/lite/c/common.h" |
|
|
#include "edge-impulse-sdk/tensorflow/lite/c/c_api_types.h" |
|
|
|
|
|
#ifndef TF_LITE_STATIC_MEMORY |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
#endif |
|
|
|
|
|
int TfLiteIntArrayGetSizeInBytes(int size) { |
|
|
static TfLiteIntArray dummy; |
|
|
return sizeof(dummy) + sizeof(dummy.data[0]) * size; |
|
|
} |
|
|
|
|
|
int TfLiteIntArrayEqual(const TfLiteIntArray* a, const TfLiteIntArray* b) { |
|
|
if (a == b) return 1; |
|
|
if (a == NULL || b == NULL) return 0; |
|
|
return TfLiteIntArrayEqualsArray(a, b->size, b->data); |
|
|
} |
|
|
|
|
|
int TfLiteIntArrayEqualsArray(const TfLiteIntArray* a, int b_size, |
|
|
const int b_data[]) { |
|
|
if (a == NULL) return (b_size == 0); |
|
|
if (a->size != b_size) return 0; |
|
|
int i = 0; |
|
|
for (; i < a->size; i++) |
|
|
if (a->data[i] != b_data[i]) return 0; |
|
|
return 1; |
|
|
} |
|
|
|
|
|
#ifndef TF_LITE_STATIC_MEMORY |
|
|
|
|
|
TfLiteIntArray* TfLiteIntArrayCreate(int size) { |
|
|
int alloc_size = TfLiteIntArrayGetSizeInBytes(size); |
|
|
if (alloc_size <= 0) return NULL; |
|
|
TfLiteIntArray* ret = (TfLiteIntArray*)malloc(alloc_size); |
|
|
if (!ret) return ret; |
|
|
ret->size = size; |
|
|
return ret; |
|
|
} |
|
|
|
|
|
TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src) { |
|
|
if (!src) return NULL; |
|
|
TfLiteIntArray* ret = TfLiteIntArrayCreate(src->size); |
|
|
if (ret) { |
|
|
memcpy(ret->data, src->data, src->size * sizeof(int)); |
|
|
} |
|
|
return ret; |
|
|
} |
|
|
|
|
|
void TfLiteIntArrayFree(TfLiteIntArray* a) { free(a); } |
|
|
|
|
|
#endif |
|
|
|
|
|
int TfLiteFloatArrayGetSizeInBytes(int size) { |
|
|
static TfLiteFloatArray dummy; |
|
|
return sizeof(dummy) + sizeof(dummy.data[0]) * size; |
|
|
} |
|
|
|
|
|
#ifndef TF_LITE_STATIC_MEMORY |
|
|
|
|
|
TfLiteFloatArray* TfLiteFloatArrayCreate(int size) { |
|
|
TfLiteFloatArray* ret = |
|
|
(TfLiteFloatArray*)malloc(TfLiteFloatArrayGetSizeInBytes(size)); |
|
|
ret->size = size; |
|
|
return ret; |
|
|
} |
|
|
|
|
|
void TfLiteFloatArrayFree(TfLiteFloatArray* a) { free(a); } |
|
|
|
|
|
void TfLiteTensorDataFree(TfLiteTensor* t) { |
|
|
if (t->allocation_type == kTfLiteDynamic || |
|
|
t->allocation_type == kTfLitePersistentRo) { |
|
|
free(t->data.raw); |
|
|
} |
|
|
t->data.raw = NULL; |
|
|
} |
|
|
|
|
|
void TfLiteQuantizationFree(TfLiteQuantization* quantization) { |
|
|
if (quantization->type == kTfLiteAffineQuantization) { |
|
|
TfLiteAffineQuantization* q_params = |
|
|
(TfLiteAffineQuantization*)(quantization->params); |
|
|
if (q_params->scale) { |
|
|
TfLiteFloatArrayFree(q_params->scale); |
|
|
q_params->scale = NULL; |
|
|
} |
|
|
if (q_params->zero_point) { |
|
|
TfLiteIntArrayFree(q_params->zero_point); |
|
|
q_params->zero_point = NULL; |
|
|
} |
|
|
free(q_params); |
|
|
} |
|
|
quantization->params = NULL; |
|
|
quantization->type = kTfLiteNoQuantization; |
|
|
} |
|
|
|
|
|
void TfLiteSparsityFree(TfLiteSparsity* sparsity) { |
|
|
if (sparsity == NULL) { |
|
|
return; |
|
|
} |
|
|
|
|
|
if (sparsity->traversal_order) { |
|
|
TfLiteIntArrayFree(sparsity->traversal_order); |
|
|
sparsity->traversal_order = NULL; |
|
|
} |
|
|
|
|
|
if (sparsity->block_map) { |
|
|
TfLiteIntArrayFree(sparsity->block_map); |
|
|
sparsity->block_map = NULL; |
|
|
} |
|
|
|
|
|
if (sparsity->dim_metadata) { |
|
|
int i = 0; |
|
|
for (; i < sparsity->dim_metadata_size; i++) { |
|
|
TfLiteDimensionMetadata metadata = sparsity->dim_metadata[i]; |
|
|
if (metadata.format == kTfLiteDimSparseCSR) { |
|
|
TfLiteIntArrayFree(metadata.array_segments); |
|
|
metadata.array_segments = NULL; |
|
|
TfLiteIntArrayFree(metadata.array_indices); |
|
|
metadata.array_indices = NULL; |
|
|
} |
|
|
} |
|
|
free(sparsity->dim_metadata); |
|
|
sparsity->dim_metadata = NULL; |
|
|
} |
|
|
|
|
|
free(sparsity); |
|
|
} |
|
|
|
|
|
void TfLiteTensorFree(TfLiteTensor* t) { |
|
|
TfLiteTensorDataFree(t); |
|
|
if (t->dims) TfLiteIntArrayFree(t->dims); |
|
|
t->dims = NULL; |
|
|
|
|
|
if (t->dims_signature) { |
|
|
TfLiteIntArrayFree((TfLiteIntArray *) t->dims_signature); |
|
|
} |
|
|
t->dims_signature = NULL; |
|
|
|
|
|
TfLiteQuantizationFree(&t->quantization); |
|
|
TfLiteSparsityFree(t->sparsity); |
|
|
t->sparsity = NULL; |
|
|
} |
|
|
|
|
|
void TfLiteTensorReset(TfLiteType type, const char* name, TfLiteIntArray* dims, |
|
|
TfLiteQuantizationParams quantization, char* buffer, |
|
|
size_t size, TfLiteAllocationType allocation_type, |
|
|
const void* allocation, bool is_variable, |
|
|
TfLiteTensor* tensor) { |
|
|
TfLiteTensorFree(tensor); |
|
|
tensor->type = type; |
|
|
tensor->name = name; |
|
|
tensor->dims = dims; |
|
|
tensor->params = quantization; |
|
|
tensor->data.raw = buffer; |
|
|
tensor->bytes = size; |
|
|
tensor->allocation_type = allocation_type; |
|
|
tensor->allocation = allocation; |
|
|
tensor->is_variable = is_variable; |
|
|
|
|
|
tensor->quantization.type = kTfLiteNoQuantization; |
|
|
tensor->quantization.params = NULL; |
|
|
} |
|
|
|
|
|
void TfLiteTensorRealloc(size_t num_bytes, TfLiteTensor* tensor) { |
|
|
if (tensor->allocation_type != kTfLiteDynamic && |
|
|
tensor->allocation_type != kTfLitePersistentRo) { |
|
|
return; |
|
|
} |
|
|
|
|
|
if (!tensor->data.raw) { |
|
|
tensor->data.raw = malloc(num_bytes); |
|
|
} else if (num_bytes > tensor->bytes) { |
|
|
tensor->data.raw = realloc(tensor->data.raw, num_bytes); |
|
|
} |
|
|
tensor->bytes = num_bytes; |
|
|
} |
|
|
#endif |
|
|
|
|
|
const char* TfLiteTypeGetName(TfLiteType type) { |
|
|
switch (type) { |
|
|
case kTfLiteNoType: |
|
|
return "NOTYPE"; |
|
|
case kTfLiteFloat32: |
|
|
return "FLOAT32"; |
|
|
case kTfLiteInt16: |
|
|
return "INT16"; |
|
|
case kTfLiteInt32: |
|
|
return "INT32"; |
|
|
case kTfLiteUInt32: |
|
|
return "UINT32"; |
|
|
case kTfLiteUInt8: |
|
|
return "UINT8"; |
|
|
case kTfLiteInt8: |
|
|
return "INT8"; |
|
|
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 kTfLiteFloat64: |
|
|
return "FLOAT64"; |
|
|
case kTfLiteResource: |
|
|
return "RESOURCE"; |
|
|
case kTfLiteVariant: |
|
|
return "VARIANT"; |
|
|
} |
|
|
return "Unknown type"; |
|
|
} |
|
|
|
|
|
TfLiteDelegate TfLiteDelegateCreate() { |
|
|
TfLiteDelegate d = { |
|
|
.data_ = NULL, |
|
|
.Prepare = NULL, |
|
|
.CopyFromBufferHandle = NULL, |
|
|
.CopyToBufferHandle = NULL, |
|
|
.FreeBufferHandle = NULL, |
|
|
.flags = kTfLiteDelegateFlagsNone, |
|
|
}; |
|
|
return d; |
|
|
} |
|
|
|