| 43 | } |
| 44 | |
| 45 | TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { |
| 46 | const OpData* op_data = reinterpret_cast<OpData*>(node->user_data); |
| 47 | |
| 48 | TF_LITE_ENSURE(context, node->inputs->size > 0); |
| 49 | |
| 50 | // The first input is the condition. |
| 51 | const TfLiteTensor* cond = GetInput(context, node, 0); |
| 52 | // Currently only bool is supported. |
| 53 | // TODO(ycling): Support other types since TensorFlow also support |
| 54 | // non-bool types as condition. |
| 55 | TF_LITE_ENSURE_EQ(context, cond->type, kTfLiteBool); |
| 56 | TF_LITE_ENSURE_EQ(context, NumElements(cond), 1); |
| 57 | |
| 58 | // The first input of the node is the condition. The rest of inputs are |
| 59 | // passed to the branch subgraphs. Therefore, the number of subgraph inputs |
| 60 | // will be the number of node inputs - 1. |
| 61 | int num_inputs = node->inputs->size - 1; |
| 62 | int num_outputs = node->outputs->size; |
| 63 | |
| 64 | Subgraph* this_subgraph = reinterpret_cast<Subgraph*>(context->impl_); |
| 65 | auto* subgraphs = this_subgraph->GetSubgraphs(); |
| 66 | TF_LITE_ENSURE(context, op_data->then_subgraph_index < subgraphs->size()); |
| 67 | TF_LITE_ENSURE(context, op_data->else_subgraph_index < subgraphs->size()); |
| 68 | |
| 69 | Subgraph* then_subgraph = (*subgraphs)[op_data->then_subgraph_index].get(); |
| 70 | Subgraph* else_subgraph = (*subgraphs)[op_data->else_subgraph_index].get(); |
| 71 | |
| 72 | for (auto* subgraph : {then_subgraph, else_subgraph}) { |
| 73 | TF_LITE_ENSURE_EQ(context, num_inputs, subgraph->inputs().size()); |
| 74 | TF_LITE_ENSURE_EQ(context, num_outputs, subgraph->outputs().size()); |
| 75 | } |
| 76 | |
| 77 | bool has_dynamic_output_tensors = false; |
| 78 | for (auto* subgraph : {then_subgraph, else_subgraph}) { |
| 79 | for (int i = 0; i < num_inputs; ++i) { |
| 80 | // The first input of the node is the condition. The indices of the inputs |
| 81 | // passed to the subgraphs are offset by 1. |
| 82 | const TfLiteTensor* input = GetInput(context, node, i + 1); |
| 83 | std::vector<int> dims(input->dims->data, |
| 84 | input->dims->data + input->dims->size); |
| 85 | subgraph->ResizeInputTensor(i, dims); |
| 86 | TfLiteTensor* subgraph_input = subgraph->tensor(subgraph->inputs()[i]); |
| 87 | TF_LITE_ENSURE_EQ(context, input->type, subgraph_input->type); |
| 88 | } |
| 89 | // Note: The `Prepare` function is responsible to run `AllocateTensors` on |
| 90 | // both subgraphs. It's intentionally not to break out of the loop when |
| 91 | // finding a dynamic output tensor. |
| 92 | TF_LITE_ENSURE_OK(context, subgraph->AllocateTensors()); |
| 93 | has_dynamic_output_tensors |= subgraph->HasDynamicTensors(); |
| 94 | } |
| 95 | |
| 96 | if (!has_dynamic_output_tensors) { |
| 97 | for (int i = 0; i < num_outputs; ++i) { |
| 98 | TfLiteTensor* then_output = |
| 99 | then_subgraph->tensor(then_subgraph->outputs()[i]); |
| 100 | TfLiteTensor* else_output = |
| 101 | else_subgraph->tensor(else_subgraph->outputs()[i]); |
| 102 | // If the 2 subgraphs have static but different output shapes, the output |
no test coverage detected