1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/lite/c/common.h"
17 #include "tensorflow/lite/c/c_api_types.h"
18 
19 #ifndef TF_LITE_STATIC_MEMORY
20 #include <stdlib.h>
21 #include <string.h>
22 #endif  // TF_LITE_STATIC_MEMORY
23 
TfLiteIntArrayGetSizeInBytes(int size)24 int TfLiteIntArrayGetSizeInBytes(int size) {
25   static TfLiteIntArray dummy;
26   return sizeof(dummy) + sizeof(dummy.data[0]) * size;
27 }
28 
TfLiteIntArrayEqual(const TfLiteIntArray * a,const TfLiteIntArray * b)29 int TfLiteIntArrayEqual(const TfLiteIntArray* a, const TfLiteIntArray* b) {
30   if (a == b) return 1;
31   if (a == NULL || b == NULL) return 0;
32   return TfLiteIntArrayEqualsArray(a, b->size, b->data);
33 }
34 
TfLiteIntArrayEqualsArray(const TfLiteIntArray * a,int b_size,const int b_data[])35 int TfLiteIntArrayEqualsArray(const TfLiteIntArray* a, int b_size,
36                               const int b_data[]) {
37   if (a == NULL) return (b_size == 0);
38   if (a->size != b_size) return 0;
39   int i = 0;
40   for (; i < a->size; i++)
41     if (a->data[i] != b_data[i]) return 0;
42   return 1;
43 }
44 
45 #ifndef TF_LITE_STATIC_MEMORY
46 
TfLiteIntArrayCreate(int size)47 TfLiteIntArray* TfLiteIntArrayCreate(int size) {
48   TfLiteIntArray* ret =
49       (TfLiteIntArray*)malloc(TfLiteIntArrayGetSizeInBytes(size));
50   ret->size = size;
51   return ret;
52 }
53 
TfLiteIntArrayCopy(const TfLiteIntArray * src)54 TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src) {
55   if (!src) return NULL;
56   TfLiteIntArray* ret = TfLiteIntArrayCreate(src->size);
57   if (ret) {
58     memcpy(ret->data, src->data, src->size * sizeof(int));
59   }
60   return ret;
61 }
62 
TfLiteIntArrayFree(TfLiteIntArray * a)63 void TfLiteIntArrayFree(TfLiteIntArray* a) { free(a); }
64 
65 #endif  // TF_LITE_STATIC_MEMORY
66 
TfLiteFloatArrayGetSizeInBytes(int size)67 int TfLiteFloatArrayGetSizeInBytes(int size) {
68   static TfLiteFloatArray dummy;
69   return sizeof(dummy) + sizeof(dummy.data[0]) * size;
70 }
71 
72 #ifndef TF_LITE_STATIC_MEMORY
73 
TfLiteFloatArrayCreate(int size)74 TfLiteFloatArray* TfLiteFloatArrayCreate(int size) {
75   TfLiteFloatArray* ret =
76       (TfLiteFloatArray*)malloc(TfLiteFloatArrayGetSizeInBytes(size));
77   ret->size = size;
78   return ret;
79 }
80 
TfLiteFloatArrayFree(TfLiteFloatArray * a)81 void TfLiteFloatArrayFree(TfLiteFloatArray* a) { free(a); }
82 
TfLiteTensorDataFree(TfLiteTensor * t)83 void TfLiteTensorDataFree(TfLiteTensor* t) {
84   if (t->allocation_type == kTfLiteDynamic ||
85       t->allocation_type == kTfLitePersistentRo) {
86     free(t->data.raw);
87   }
88   t->data.raw = NULL;
89 }
90 
TfLiteQuantizationFree(TfLiteQuantization * quantization)91 void TfLiteQuantizationFree(TfLiteQuantization* quantization) {
92   if (quantization->type == kTfLiteAffineQuantization) {
93     TfLiteAffineQuantization* q_params =
94         (TfLiteAffineQuantization*)(quantization->params);
95     if (q_params->scale) {
96       TfLiteFloatArrayFree(q_params->scale);
97       q_params->scale = NULL;
98     }
99     if (q_params->zero_point) {
100       TfLiteIntArrayFree(q_params->zero_point);
101       q_params->zero_point = NULL;
102     }
103     free(q_params);
104   }
105   quantization->params = NULL;
106   quantization->type = kTfLiteNoQuantization;
107 }
108 
TfLiteSparsityFree(TfLiteSparsity * sparsity)109 void TfLiteSparsityFree(TfLiteSparsity* sparsity) {
110   if (sparsity == NULL) {
111     return;
112   }
113 
114   if (sparsity->traversal_order) {
115     TfLiteIntArrayFree(sparsity->traversal_order);
116     sparsity->traversal_order = NULL;
117   }
118 
119   if (sparsity->block_map) {
120     TfLiteIntArrayFree(sparsity->block_map);
121     sparsity->block_map = NULL;
122   }
123 
124   if (sparsity->dim_metadata) {
125     int i = 0;
126     for (; i < sparsity->dim_metadata_size; i++) {
127       TfLiteDimensionMetadata metadata = sparsity->dim_metadata[i];
128       if (metadata.format == kTfLiteDimSparseCSR) {
129         TfLiteIntArrayFree(metadata.array_segments);
130         metadata.array_segments = NULL;
131         TfLiteIntArrayFree(metadata.array_indices);
132         metadata.array_indices = NULL;
133       }
134     }
135     free(sparsity->dim_metadata);
136     sparsity->dim_metadata = NULL;
137   }
138 
139   free(sparsity);
140 }
141 
TfLiteTensorFree(TfLiteTensor * t)142 void TfLiteTensorFree(TfLiteTensor* t) {
143   TfLiteTensorDataFree(t);
144   if (t->dims) TfLiteIntArrayFree(t->dims);
145   t->dims = NULL;
146 
147   if (t->dims_signature) {
148     TfLiteIntArrayFree((TfLiteIntArray *) t->dims_signature);
149   }
150   t->dims_signature = NULL;
151 
152   TfLiteQuantizationFree(&t->quantization);
153   TfLiteSparsityFree(t->sparsity);
154   t->sparsity = NULL;
155 }
156 
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)157 void TfLiteTensorReset(TfLiteType type, const char* name, TfLiteIntArray* dims,
158                        TfLiteQuantizationParams quantization, char* buffer,
159                        size_t size, TfLiteAllocationType allocation_type,
160                        const void* allocation, bool is_variable,
161                        TfLiteTensor* tensor) {
162   TfLiteTensorFree(tensor);
163   tensor->type = type;
164   tensor->name = name;
165   tensor->dims = dims;
166   tensor->params = quantization;
167   tensor->data.raw = buffer;
168   tensor->bytes = size;
169   tensor->allocation_type = allocation_type;
170   tensor->allocation = allocation;
171   tensor->is_variable = is_variable;
172 
173   tensor->quantization.type = kTfLiteNoQuantization;
174   tensor->quantization.params = NULL;
175 }
176 
TfLiteTensorRealloc(size_t num_bytes,TfLiteTensor * tensor)177 void TfLiteTensorRealloc(size_t num_bytes, TfLiteTensor* tensor) {
178   if (tensor->allocation_type != kTfLiteDynamic &&
179       tensor->allocation_type != kTfLitePersistentRo) {
180     return;
181   }
182   // TODO(b/145340303): Tensor data should be aligned.
183   if (!tensor->data.raw) {
184     tensor->data.raw = malloc(num_bytes);
185   } else if (num_bytes > tensor->bytes) {
186     tensor->data.raw = realloc(tensor->data.raw, num_bytes);
187   }
188   tensor->bytes = num_bytes;
189 }
190 #endif  // TF_LITE_STATIC_MEMORY
191 
TfLiteTypeGetName(TfLiteType type)192 const char* TfLiteTypeGetName(TfLiteType type) {
193   switch (type) {
194     case kTfLiteNoType:
195       return "NOTYPE";
196     case kTfLiteFloat32:
197       return "FLOAT32";
198     case kTfLiteInt16:
199       return "INT16";
200     case kTfLiteInt32:
201       return "INT32";
202     case kTfLiteUInt32:
203       return "UINT32";
204     case kTfLiteUInt8:
205       return "UINT8";
206     case kTfLiteInt8:
207       return "INT8";
208     case kTfLiteInt64:
209       return "INT64";
210     case kTfLiteUInt64:
211       return "UINT64";
212     case kTfLiteBool:
213       return "BOOL";
214     case kTfLiteComplex64:
215       return "COMPLEX64";
216     case kTfLiteComplex128:
217       return "COMPLEX128";
218     case kTfLiteString:
219       return "STRING";
220     case kTfLiteFloat16:
221       return "FLOAT16";
222     case kTfLiteFloat64:
223       return "FLOAT64";
224     case kTfLiteResource:
225       return "RESOURCE";
226     case kTfLiteVariant:
227       return "VARIANT";
228   }
229   return "Unknown type";
230 }
231 
TfLiteDelegateCreate()232 TfLiteDelegate TfLiteDelegateCreate() {
233   TfLiteDelegate d = {
234       .data_ = NULL,
235       .Prepare = NULL,
236       .CopyFromBufferHandle = NULL,
237       .CopyToBufferHandle = NULL,
238       .FreeBufferHandle = NULL,
239       .flags = kTfLiteDelegateFlagsNone,
240   };
241   return d;
242 }
243