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