xref: /aosp_15_r20/external/mesa3d/include/tensorflow/lite/core/c/c_api_opaque.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* Copyright 2022 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 #ifndef TENSORFLOW_LITE_CORE_C_C_API_OPAQUE_H_
16 #define TENSORFLOW_LITE_CORE_C_C_API_OPAQUE_H_
17 
18 #include "tensorflow/lite/core/c/c_api.h"
19 #include "tensorflow/lite/core/c/c_api_types.h"  // IWYU pragma: export
20 #include "tensorflow/lite/core/c/common.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif  // __cplusplus
25 
26 // --------------------------------------------------------------------------
27 /// C API for TensorFlow Lite Opaque Types.
28 ///
29 /// These APIs are accessors for TFLite Opaque Types.  These APIs are primarily
30 /// intended to be used by delegates and custom OP implementations.
31 ///
32 /// WARNING: This is an experimental API and subject to change.
33 
34 // --------------------------------------------------------------------------
35 // Accessors for TfLiteOpaqueTensor.
36 
37 // Returns the type of a tensor element.
38 TFL_CAPI_EXPORT extern TfLiteType TfLiteOpaqueTensorType(
39     const TfLiteOpaqueTensor* opaque_tensor);
40 
41 // Returns the number of dimensions that the tensor has.  Returns -1 in case
42 // the 'opaque_tensor' does not have its dimensions property set.
43 TFL_CAPI_EXPORT extern int32_t TfLiteOpaqueTensorNumDims(
44     const TfLiteOpaqueTensor* opaque_tensor);
45 
46 // Returns the length of the tensor in the "dim_index" dimension.
47 TFL_CAPI_EXPORT extern int32_t TfLiteOpaqueTensorDim(
48     const TfLiteOpaqueTensor* opaque_tensor, int32_t dim_index);
49 
50 // Loads into the provided 'num_dims' the number of dimensions that the tensor's
51 // signature has. Returns 'kTfLiteOk' if 'num_dims' was successfully loaded. Any
52 // other return code indicates an error and 'num_dims' won't be loaded.
53 //
54 // A tensor's dimension signature encodes shapes with unknown dimensions with
55 // -1.  E.g. for a tensor with three dimensions, whose first dimension has an
56 // unknown size, and the second and third dimension have a size of 2, the
57 // dimension signature is [-1,2,2], and 'TfLiteOpaqueTensorGetNumDimsSignature'
58 // loads 3 into 'num_dims'. If the tensor does not have its dimension signature
59 // field set then 'num_dims' is set to -1.
60 TFL_CAPI_EXPORT extern TfLiteStatus TfLiteOpaqueTensorGetNumDimsSignature(
61     const TfLiteOpaqueTensor* opaque_tensor, int32_t* num_dims);
62 
63 // Loads into the provided 'dim_length' the length of the tensor in the
64 // 'dim_index' signature dimension or -1 if that dimension has unknown length.
65 // Returns 'kTfLiteOk' if 'dim_length' was successfully loaded. Any
66 // other return code indicates an error and 'dim_length' won't be loaded.
67 TFL_CAPI_EXPORT extern TfLiteStatus TfLiteOpaqueTensorGetDimSignature(
68     const TfLiteOpaqueTensor* opaque_tensor, int32_t dim_index,
69     int32_t* dim_length);
70 
71 // Returns 'non-zero' if the provided 'opaque_tensor' is a variable, and returns
72 // zero otherwise.
73 TFL_CAPI_EXPORT extern int TfLiteOpaqueTensorIsVariable(
74     const TfLiteOpaqueTensor* opaque_tensor);
75 
76 // Returns the size of the underlying data in bytes.
77 TFL_CAPI_EXPORT extern size_t TfLiteOpaqueTensorByteSize(
78     const TfLiteOpaqueTensor* opaque_tensor);
79 
80 // Returns a pointer to the underlying data buffer.
81 TFL_CAPI_EXPORT extern void* TfLiteOpaqueTensorData(
82     const TfLiteOpaqueTensor* opaque_tensor);
83 
84 // Returns the 'opaque_tensor's allocation type.
85 TFL_CAPI_EXPORT extern TfLiteAllocationType TfLiteOpaqueTensorGetAllocationType(
86     const TfLiteOpaqueTensor* opaque_tensor);
87 
88 // Returns the (null-terminated) name of the tensor.
89 TFL_CAPI_EXPORT extern const char* TfLiteOpaqueTensorName(
90     const TfLiteOpaqueTensor* opaque_tensor);
91 
92 // Returns the 'opaque_tensor's quantization information.
93 TFL_CAPI_EXPORT extern TfLiteQuantization TfLiteOpaqueTensorGetQuantization(
94     const TfLiteOpaqueTensor* opaque_tensor);
95 
96 // Returns the 'opaque_tensor's quantization parameters.
97 TFL_CAPI_EXPORT extern TfLiteQuantizationParams
98 TfLiteOpaqueTensorGetQuantizationParams(
99     const TfLiteOpaqueTensor* opaque_tensor);
100 
101 // Copies from the provided input buffer into the tensor's buffer.
102 TFL_CAPI_EXPORT extern TfLiteStatus TfLiteOpaqueTensorCopyFromBuffer(
103     TfLiteOpaqueTensor* opaque_tensor, const void* input_data,
104     size_t input_data_size);
105 
106 // Copies to the provided output buffer from the tensor's buffer.
107 TFL_CAPI_EXPORT extern TfLiteStatus TfLiteOpaqueTensorCopyToBuffer(
108     const TfLiteOpaqueTensor* opaque_tensor, void* output_data,
109     size_t output_data_size);
110 
111 // --------------------------------------------------------------------------
112 // Accessors for TfLiteOpaqueNode.
113 
114 // Returns the input tensor of the given node.
115 TFL_CAPI_EXPORT extern const TfLiteOpaqueTensor* TfLiteOpaqueNodeGetInput(
116     const TfLiteOpaqueContext* opaque_context,
117     const TfLiteOpaqueNode* opaque_node, int index);
118 
119 // Returns the output tensor of the given node.
120 TFL_CAPI_EXPORT extern TfLiteOpaqueTensor* TfLiteOpaqueNodeGetOutput(
121     TfLiteOpaqueContext* opaque_context, const TfLiteOpaqueNode* opaque_node,
122     int index);
123 
124 // Gets the number of input tensors of the provided 'opaque_node'.
125 TFL_CAPI_EXPORT int TfLiteOpaqueNodeNumberOfInputs(
126     const TfLiteOpaqueNode* opaque_node);
127 
128 // Gets the number of output tensors of the provided 'opaque_node'.
129 TFL_CAPI_EXPORT int TfLiteOpaqueNodeNumberOfOutputs(
130     const TfLiteOpaqueNode* opaque_node);
131 
132 // Returns opaque data provided by the node implementer. The value returned
133 // from this function is the value that was returned from the `init` callback
134 // that was passed to `TfLiteRegistrationExternalSetInit`.
135 TFL_CAPI_EXPORT extern void* TfLiteOpaqueNodeGetUserData(
136     const TfLiteOpaqueNode* opaque_node);
137 
138 // Returns the builtin data associated with the provided 'opaque_node'.
139 //
140 // The builtin init data associated with a node would typically be set during
141 // the creation of the associated interpreter, through a mechanism like the
142 // interpreter builder that loads a TFLite model and initialises the
143 // interpreter's nodes accordingly.  Under these conditions the returned address
144 // remains valid throughout the lifetime of the 'opaque_node'.
145 TFL_CAPI_EXPORT extern void* TfLiteOpaqueNodeGetBuiltinData(
146     const TfLiteOpaqueNode* opaque_node);
147 
148 // Loads into the provided '*init_data' pointer the address of the custom init
149 // data associated with the provided 'opaque_node'.  The length of data is
150 // loaded into the provided 'size' pointer.  Returns 'kTfLiteOk' in case
151 // of success.  Any other return value indicates a failure and will leave
152 // 'init_data' and 'size' in an unspecified state.
153 //
154 // The custom init data associated with a node would typically be set during the
155 // creation of the associated interpreter, through a mechanism like the
156 // interpreter builder that loads a TFLite model and initialises the
157 // interpreter's nodes accordingly.  Under these conditions the returned address
158 // remains valid throughout the lifetime of the 'opaque_node'.
159 TFL_CAPI_EXPORT extern TfLiteStatus TfLiteOpaqueNodeGetCustomInitialData(
160     const TfLiteOpaqueNode* opaque_node, const void** init_data, int* size);
161 
162 // Loads into the provided '*inputs' pointer the starting address of an array
163 // of indices representing the tensors that are inputs of the provided
164 // 'opaque_node'. The length of the array is loaded into the provided
165 // 'num_inputs' pointer. Returns 'kTfLiteOk' in case of success.  Any other
166 // return value indicates a failure and will leave 'inputs' and
167 // 'num_inputs' in an unspecified state.
168 //
169 // The input tensors associated with a node would typically be set during the
170 // creation of the associated interpreter, through a mechanism like the
171 // interpreter builder that loads a TFLite model and initialises the
172 // interpreter's nodes accordingly.  Under these conditions the loaded address
173 // remains valid throughout the lifetime of the 'opaque_node'.
174 TFL_CAPI_EXPORT TfLiteStatus TfLiteOpaqueNodeInputs(
175     const TfLiteOpaqueNode* opaque_node, const int** inputs, int* num_inputs);
176 
177 // Loads into the provided '*outputs' pointer the starting address of an array
178 // of indices representing the tensors that are outputs of the provided
179 // 'opaque_node'. The length of the array is loaded into the provided
180 // 'num_outputs' pointer. Returns 'kTfLiteOk' in case of success.  Any other
181 // return value indicates a failure and will leave 'outputs' and
182 // 'num_outputs' in an unspecified state.
183 //
184 // The output tensors associated with a node would typically be set during the
185 // creation of the associated interpreter, through a mechanism like the
186 // interpreter builder that loads a TFLite model and initialises the
187 // interpreter's nodes accordingly.  Under these conditions the loaded address
188 // remains valid throughout the lifetime of the 'opaque_node'.
189 TFL_CAPI_EXPORT TfLiteStatus TfLiteOpaqueNodeOutputs(
190     const TfLiteOpaqueNode* opaque_node, const int** outputs, int* num_outputs);
191 
192 // Loads into the provided '*temporaries' pointer the starting address of an
193 // array of indices representing the temporary tensors associated with the
194 // provided 'opaque_node'. The length of the array is loaded into the provided
195 // 'num_temporaries' pointer. Returns 'kTfLiteOk' in case of success.  Any other
196 // return value indicates a failure and will leave 'temporaries' and
197 // 'num_temporaries' in an unspecified state.
198 //
199 // The temporary tensors associated with a node would typically be set during
200 // the creation of the associated interpreter, through a mechanism like the
201 // interpreter builder that loads a TFLite model and initialises the
202 // interpreter's nodes accordingly.  Under these conditions the loaded address
203 // remains valid throughout the lifetime of the 'opaque_node'.
204 TFL_CAPI_EXPORT
205 TfLiteStatus TfLiteOpaqueNodeTemporaries(const TfLiteOpaqueNode* opaque_node,
206                                          const int** temporaries,
207                                          int* num_temporaries);
208 
209 // --------------------------------------------------------------------------
210 // Accessors for TfLiteOpaqueContext.
211 
212 typedef struct TfLiteIntArray TfLiteIntArray;
213 
214 // Loads the provided `execution_plan` associated with the provided
215 // `opaque_context`.  Returns `kTfLiteOk` if the `execution_plan` was
216 // successfully loaded.  A return value different from `kTfLiteOk` indicates a
217 // failure and the `execution_plan` will be left in an unspecified state.
218 TFL_CAPI_EXPORT extern TfLiteStatus TfLiteOpaqueContextGetExecutionPlan(
219     TfLiteOpaqueContext* opaque_context, TfLiteIntArray** execution_plan);
220 
221 // Given the specified 'opaque_context' and 'node_index', load the caller's
222 // opaque '*node' and '*registration_external' pointer.  Return 'kTfLiteOk' if
223 // both the '*node' as well as the '*registration_external' have been loaded
224 // correctly.  Any other return code indicates a failure and both '*node' as
225 // well as '*registration_external' will be in an unspecified state.
226 //
227 // A caller can obtain a node's index by calling
228 // 'TfLiteOpaqueContextGetExecutionPlan', which provides an array of node
229 // indices, sorted in execution order.  A node index might also come from the
230 // data structures passed to the delegate kernel's callback parameters, like the
231 // delegate parameters data structure passed to the 'init' callback that
232 // contains an array of node indices that are meant to be handled by the
233 // delegate kernel.
234 //
235 // This function is expected to be called from within a delegate callback, like
236 // 'Prepare', or a delegate kernel callback (i.e., a callback registered with
237 // a 'TfLiteRegistrationExternal' object).
238 //
239 // The loaded '*node' and '*registration_external' pointers will generally
240 // remain valid for the lifetime of the associated 'opaque_context', but can be
241 // invalidated through API calls where delegates get un-applied, like API calls
242 // that modify the model graph via a delegate, or if input tensors get re-sized.
243 //
244 // TODO(b/237983452): Further clarify the lifetime guarantees of pointers that
245 // are returned to the users and which actions invalidate them.
246 TFL_CAPI_EXPORT TfLiteStatus TfLiteOpaqueContextGetNodeAndRegistration(
247     struct TfLiteOpaqueContext* opaque_context, int node_index,
248     TfLiteOpaqueNode** node,
249     TfLiteRegistrationExternal** registration_external);
250 
251 // WARNING: This is an experimental API and subject to change.
252 // Entry point for C API ReplaceNodeSubsetsWithDelegateKernels
253 //
254 // Replaces the specified `nodes_to_replace` that are associated with the
255 // provided `opaque_context` with delegate kernels.  The provided
256 // `registration_external` represents the delegate kernel and will be used for
257 // each node subset that will be delegate to the provided `opaque_delegate`.
258 //
259 // The TF Lite runtime will take ownership of the `registration_external` and
260 // will delete it when the associated `opaque_context` gets destroyed.
261 //
262 // The ownership of the `nodes_to_replace` and the `opaque_delegate` remains
263 // with the caller.
264 TFL_CAPI_EXPORT TfLiteStatus
265 TfLiteOpaqueContextReplaceNodeSubsetsWithDelegateKernels(
266     struct TfLiteOpaqueContext* opaque_context,
267     TfLiteRegistrationExternal* registration_external,
268     const TfLiteIntArray* nodes_to_replace,
269     TfLiteOpaqueDelegate* opaque_delegate);
270 
271 // Returns modifiable access to the opaque tensor that corresponds to the
272 // specified `index` and is associated with the provided `opaque_context`.
273 //
274 // This requires the `index` to be between 0 and N - 1, where N is the
275 // number of tensors in the model.
276 //
277 // Typically the tensors associated with the `context` would be set
278 // during the initialization of the `interpreter` that the `context` belongs to,
279 // through a mechanism like the `InterpreterBuilder`, and remain unchanged
280 // throughout the lifetime of the interpreter.  However, there are some
281 // circumstances in which the pointer may not remain valid throughout the
282 // lifetime of the interpreter, because calls to `AddTensors` on the interpreter
283 // invalidate the returned pointer.
284 //
285 // The ownership of the tensor remains with the TFLite runtime, meaning the
286 // caller should not deallocate the pointer.
287 TFL_CAPI_EXPORT
288 TfLiteOpaqueTensor* TfLiteOpaqueContextGetOpaqueTensor(
289     const TfLiteOpaqueContext* opaque_context, int index);
290 
291 // Loads into the provided '*inputs' pointer the starting address of an array
292 // of indices representing the tensors that are inputs to the subgraph that is
293 // associated with the provided 'opaque_context'.  The length of the array is
294 // loaded into the provided 'num_inputs' pointer.  Returns 'kTfLiteOk' in case
295 // of success.  Any other return value indicates a failure and will leave
296 // 'inputs' and 'num_inputs' in an unspecified state.  Calls to 'SetInputs' on
297 // the associated subgraph invalidate the loaded pointers.
298 TFL_CAPI_EXPORT
299 TfLiteStatus TfLiteOpaqueContextGetInputs(
300     const struct TfLiteOpaqueContext* opaque_context, const int** inputs,
301     int* num_inputs);
302 
303 // Loads into the provided '*outputs' pointer the starting address of an array
304 // of indices representing the tensors that are outputs to the subgraph that is
305 // associated with the provided 'opaque_context'.  The length of the array is
306 // loaded into the provided 'num_outputs' pointer.  Returns 'kTfLiteOk' in case
307 // of success.  Any other return value indicates a failure and will leave
308 // 'outputs' and 'num_outputs' in an unspecified state.  Calls to 'SetOutputs'
309 // on the associated subgraph invalidate the loaded pointers.
310 TFL_CAPI_EXPORT
311 TfLiteStatus TfLiteOpaqueContextGetOutputs(
312     const struct TfLiteOpaqueContext* opaque_context, const int** outputs,
313     int* num_outputs);
314 
315 // Loads into the provided '*variables' pointer the starting address of an array
316 // of indices representing the tensors that are variables to the subgraph that
317 // is associated with the provided 'opaque_context'.  The length of the array is
318 // loaded into the provided 'num_variables' pointer.  Returns 'kTfLiteOk' in
319 // case of success.  Any other return value indicates a failure and will leave
320 // 'variables' and 'num_variables' in an unspecified state.  Calls to
321 // 'SetVariables' on the associated subgraph invalidate the loaded pointers.
322 TFL_CAPI_EXPORT
323 TfLiteStatus TfLiteOpaqueContextGetVariables(
324     const struct TfLiteOpaqueContext* opaque_context, const int** variables,
325     int* num_variables);
326 
327 // Returns the number of nodes associated with the provided 'opaque_context'.
328 TFL_CAPI_EXPORT
329 size_t TfLiteOpaqueContextGetNumNodes(
330     const struct TfLiteOpaqueContext* opaque_context);
331 
332 // Returns the number of tensors associated with the provided 'opaque_context'.
333 TFL_CAPI_EXPORT
334 size_t TfLiteOpaqueContextGetNumTensors(
335     const struct TfLiteOpaqueContext* opaque_context);
336 
337 // Returns the name of the subgraph that is associated with the provided
338 // 'opaque_context'.  Typically the returned pointer will remain valid
339 // throughout the lifetime of the subgraph, but may be invalidated by a call to
340 // 'Subgraph::SetName'.
341 TFL_CAPI_EXPORT
342 const char* TfLiteOpaqueContextGetName(
343     const struct TfLiteOpaqueContext* opaque_context);
344 
345 // Resizes the provided 'tensor' that is associated with the provided
346 // 'context' so that the 'tensor's shape matches the dimensionality specified
347 // via the provided 'new_size' array.  Returns 'kTfLiteOk' in
348 // case of success.  Any other return value indicates a failure and will leave
349 // the 'tensor' in an unspecified state.  The TF Lite runtime takes ownership
350 // of the 'new_size' array, even in case of failure.
351 TFL_CAPI_EXPORT
352 TfLiteStatus TfLiteOpaqueContextResizeTensor(TfLiteOpaqueContext* context,
353                                              TfLiteOpaqueTensor* tensor,
354                                              TfLiteIntArray* new_size);
355 
356 // Entry point for C API GetSubgraphContext.
357 //
358 // Retrieves the corresponding TfLiteOpaqueContext of a subgraph given a
359 // subgraph index. If an invalid subgraph index is given, then returns nullptr.
360 TFL_CAPI_EXPORT
361 TfLiteOpaqueContext* TfLiteOpaqueContextGetSubgraphContext(
362     struct TfLiteOpaqueContext* opaque_context, int subgraph_index);
363 
364 // Entry point for C API MarkSubgraphAsDelegationSkippable
365 //
366 // Marks the subgraph with the given index as "delegation-skippable". Returns
367 // kTfLiteOk if the given subgraph index is valid and is successfully marked
368 // as delegation-skippable, and an error status if the subgraph index is
369 // invalid.
370 // If a subgraph is delegation-skippable, then the subgraph will be handled by a
371 // TfLiteOpaqueDelegate (and that the delegate is supposed to be already aware
372 // of this state), and therefore, TfLiteInterpreter can skip invoking
373 // `ModifyGraphWithDelegate` on this subgraph.
374 // NOTE: This function is expected to be called only when the subgraph that
375 // `subgraph_index` is pointing to should be skipped by
376 // interpreter::ModifyGraphWithDelegate (e.g. the subgraph is part of the list
377 // of callee subgraphs of the same control flow node, and all of those callees
378 // are supported by the same delegate at once).
379 //
380 // For  example, this function can be used when the delegate is handling control
381 // flow ops like while op.
382 // E.g. A while op has condition subgraph indexed at `i` and body subgraph
383 // indexed at `j`. The op can be delegated when the following condition
384 // satisfied:
385 //   1. The delegate supports while op
386 //   2. Both condition subgraph `i` and body subgraph `j` can be fully delegated
387 //      by the delegate.
388 // Then if the delegate decides to support the while node along with both body
389 // and condition subgraphs, it should mark subgraphs `i` and `j` skippable so
390 // those two subgraphs won't be delegated separately again after being
391 // absorbed by the parent subgraph.
392 // WARNING: It is the delegate's responsibility to define when to skip
393 // subgraph->ModifyGraphWithDelegate, to check any edge cases (i.e. multiple
394 // references to the subgraph that `subgraph_index` is pointing to), and to mark
395 // that subgraph as skippable using this function.
396 TFL_CAPI_EXPORT
397 TfLiteStatus TfLiteOpaqueContextMarkSubgraphAsDelegationSkippable(
398     TfLiteOpaqueContext* opaque_context, int subgraph_index);
399 
400 // Reports an error message formed by using the provided 'format' string in
401 // combination with the data provided via the unnamed arguments following the
402 // the 'format' parameter ('...').  The intended usage and behavior is the same
403 // as with 'printf' with regards to how the data and the formatting string
404 // interact.  E.g.
405 // 'TfLiteOpaqueContextReportError(opaque_context, "a=%d b=%d", a, b);'
406 //
407 // The provided 'opaque_context' will be used for reporting the resulting error
408 // message.
409 //
410 // Note that TF Lite clients can use macros like 'TF_LITE_OPAQUE_ENSURE' to
411 // check for certain conditions to be true, and print an error message if the
412 // condition does not hold.  Direct usage of this function from application code
413 // should therefore be rare.
414 TFL_CAPI_EXPORT
415 void TfLiteOpaqueContextReportError(struct TfLiteOpaqueContext* opaque_context,
416                                     const char* format, ...);
417 
418 // Same as 'TfLiteOpaqueContextReportError', but with the variable arguments
419 // passed via a 'va_list' instead of directly.
420 //
421 // Callers that receive an ellipsis and want to forward it to
422 // to the opaque context error reporting API can add the ellipsis content to a
423 // 'va_list' and then call 'TfLiteOpaqueContextReportErrorVa'. E.g.:
424 //
425 // void MyErrorReporter(struct TfLiteOpaqueContext* opaque_context,
426 //                                     const char* format, ...) {
427 //   va_list vlist;
428 //   va_start(vlist, format);
429 //   TfLiteOpaqueContextReportErrorVa(opaque_context, format, vlist);
430 //   va_end(vlist);
431 // }
432 TFL_CAPI_EXPORT
433 void TfLiteOpaqueContextReportErrorVa(
434     struct TfLiteOpaqueContext* opaque_context, const char* format,
435     va_list vlist);
436 
437 // Since we must not depend on any libraries, define a minimal subset of
438 // error macros while avoiding names that have pre-conceived meanings like
439 // assert and check.
440 
441 // Try to make all reporting calls through TF_LITE_OPAQUE_KERNEL_LOG rather than
442 // calling the TfLiteOpaqueContextReportError function directly, so that message
443 // strings can be stripped out if the binary size needs to be severely
444 // optimized.
445 #ifndef TF_LITE_STRIP_ERROR_STRINGS
446 
447 #if !defined(TF_LITE_OPAQUE_KERNEL_LOG)
448 #define TF_LITE_OPAQUE_KERNEL_LOG(opaque_context, ...)             \
449   do {                                                             \
450     TfLiteOpaqueContextReportError((opaque_context), __VA_ARGS__); \
451   } while (false)
452 #endif
453 
454 #if !defined(TF_LITE_OPAQUE_MAYBE_KERNEL_LOG)
455 #define TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(opaque_context, ...)         \
456   do {                                                               \
457     if ((opaque_context) != nullptr) {                               \
458       TfLiteOpaqueContextReportError((opaque_context), __VA_ARGS__); \
459     }                                                                \
460   } while (false)
461 #endif
462 
463 #else  // TF_LITE_STRIP_ERROR_STRINGS
464 #define ARGS_UNUSED(...) (void)sizeof(#__VA_ARGS__)
465 
466 #if !defined(TF_LITE_OPAQUE_MAYBE_KERNEL_LOG)
467 #define TF_LITE_OPAQUE_KERNEL_LOG(opaque_context, ...) ARGS_UNUSED(__VA_ARGS__)
468 #endif
469 
470 #if !defined(TF_LITE_OPAQUE_MAYBE_KERNEL_LOG)
471 #define TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(opaque_context, ...) \
472   ARGS_UNUSED(__VA_ARGS__)
473 #endif
474 
475 #endif  // TF_LITE_STRIP_ERROR_STRINGS
476 
477 // Check whether value is true, and if not return kTfLiteError from
478 // the current function (and report the error string msg).
479 #if !defined(TF_LITE_OPAQUE_ENSURE_MSG)
480 #define TF_LITE_OPAQUE_ENSURE_MSG(opaque_context, value, msg)        \
481   do {                                                               \
482     if (!(value)) {                                                  \
483       TF_LITE_OPAQUE_KERNEL_LOG((opaque_context), __FILE__ " " msg); \
484       return kTfLiteError;                                           \
485     }                                                                \
486   } while (0)
487 #endif
488 
489 // Check whether the value `a` is true, and if not return kTfLiteError from
490 // the current function, while also reporting the location of the error.
491 #if !defined(TF_LITE_OPAQUE_ENSURE)
492 #define TF_LITE_OPAQUE_ENSURE(opaque_context, a)                           \
493   do {                                                                     \
494     if (!(a)) {                                                            \
495       TF_LITE_OPAQUE_KERNEL_LOG(opaque_context, "%s:%d: %s was not true.", \
496                                 __FILE__, __LINE__, #a);                   \
497       return kTfLiteError;                                                 \
498     }                                                                      \
499   } while (0)
500 #endif
501 
502 // Check whether the value `a == b` is true, and if not return kTfLiteError from
503 // the current function, while also reporting the location of the error.
504 // `a` and `b` may be evaluated more than once, so no side effects or
505 // extremely expensive computations should be done.
506 // NOTE: Use TF_LITE_ENSURE_TYPES_EQ if comparing TfLiteTypes.
507 #if !defined(TF_LITE_OPAQUE_ENSURE_EQ)
508 #define TF_LITE_OPAQUE_ENSURE_EQ(opaque_context, a, b)                  \
509   do {                                                                  \
510     if ((a) != (b)) {                                                   \
511       TF_LITE_OPAQUE_KERNEL_LOG((opaque_context),                       \
512                                 "%s:%d: %s != %s (%d != %d)", __FILE__, \
513                                 __LINE__, #a, #b, (a), (b));            \
514       return kTfLiteError;                                              \
515     }                                                                   \
516   } while (0)
517 #endif
518 
519 #if !defined(TF_LITE_OPAQUE_ENSURE_TYPES_EQ)
520 #define TF_LITE_OPAQUE_ENSURE_TYPES_EQ(opaque_context, a, b)                  \
521   do {                                                                        \
522     if ((a) != (b)) {                                                         \
523       TF_LITE_OPAQUE_KERNEL_LOG(                                              \
524           (opaque_context), "%s:%d: %s != %s (%s != %s)", __FILE__, __LINE__, \
525           #a, #b, TfLiteTypeGetName(a), TfLiteTypeGetName(b));                \
526       return kTfLiteError;                                                    \
527     }                                                                         \
528   } while (0)
529 #endif
530 
531 #if !defined(TF_LITE_OPAQUE_ENSURE_NEAR)
532 #define TF_LITE_OPAQUE_ENSURE_NEAR(opaque_context, a, b, epsilon)             \
533   do {                                                                        \
534     double delta = ((a) > (b)) ? ((a) - (b)) : ((b) - (a));                   \
535     if (delta > epsilon) {                                                    \
536       TF_LITE_OPAQUE_KERNEL_LOG((opaque_context),                             \
537                                 "%s:%d: %s not near %s (%f != %f)", __FILE__, \
538                                 __LINE__, #a, #b, (double)(a), (double)(b));  \
539       return kTfLiteError;                                                    \
540     }                                                                         \
541   } while (0)
542 #endif
543 
544 #ifdef __cplusplus
545 }  // extern "C"
546 #endif  // __cplusplus
547 
548 #endif  // TENSORFLOW_LITE_CORE_C_C_API_OPAQUE_H_
549