| 222 | } |
| 223 | |
| 224 | bool IsHybridOperator(const TfLiteContext* context, int builtin_code, |
| 225 | const TfLiteNode* node) { |
| 226 | switch (builtin_code) { |
| 227 | case kTfLiteBuiltinConv2d: |
| 228 | case kTfLiteBuiltinFullyConnected: { |
| 229 | const int input_id = node->inputs->data[0]; |
| 230 | const int filter_id = node->inputs->data[1]; |
| 231 | const TfLiteType input_type = context->tensors[input_id].type; |
| 232 | const TfLiteType filter_type = context->tensors[filter_id].type; |
| 233 | return IsFloat(input_type) && IsQuantized(filter_type); |
| 234 | } |
| 235 | case kTfLiteBuiltinLstm: { |
| 236 | const int input_id = node->inputs->data[0]; |
| 237 | // Input #1 is optional so use #2 to determine if hybrid. |
| 238 | const int weights_id = node->inputs->data[2]; |
| 239 | const TfLiteType input_type = context->tensors[input_id].type; |
| 240 | const TfLiteType weights_type = context->tensors[weights_id].type; |
| 241 | return isLstmFullKernel(node) && IsFloat(input_type) && |
| 242 | IsQuantized(weights_type); |
| 243 | } |
| 244 | case kTfLiteBuiltinUnidirectionalSequenceLstm: { |
| 245 | const int input_id = node->inputs->data[0]; |
| 246 | // Input #1 is optional so use #2 to determine if hybrid. |
| 247 | const int weights_id = node->inputs->data[2]; |
| 248 | const TfLiteType input_type = context->tensors[input_id].type; |
| 249 | const TfLiteType weights_type = context->tensors[weights_id].type; |
| 250 | return IsFloat(input_type) && IsQuantized(weights_type); |
| 251 | } |
| 252 | case kTfLiteBuiltinBidirectionalSequenceLstm: { |
| 253 | const int input_id = node->inputs->data[0]; |
| 254 | // Input #1 is optional so use #2 to determine if hybrid. |
| 255 | const int weights_id = node->inputs->data[2]; |
| 256 | const TfLiteType input_type = context->tensors[input_id].type; |
| 257 | const TfLiteType weights_type = context->tensors[weights_id].type; |
| 258 | return IsFloat(input_type) && IsQuantized(weights_type); |
| 259 | } |
| 260 | case kTfLiteBuiltinUnidirectionalSequenceRnn: { |
| 261 | const int input_id = node->inputs->data[0]; |
| 262 | const int weights_id = node->inputs->data[1]; |
| 263 | const TfLiteType input_type = context->tensors[input_id].type; |
| 264 | const TfLiteType weights_type = context->tensors[weights_id].type; |
| 265 | return IsFloat(input_type) && IsQuantized(weights_type); |
| 266 | } |
| 267 | default: |
| 268 | return false; |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | // When using NN API version 1.0 or 1.1, the condition below must be true for |
| 273 | // quantized versions of the following ops: |
no test coverage detected