| 29 | constexpr int kOutputTensor = 0; |
| 30 | |
| 31 | TfLiteStatus ReshapeOutput(TfLiteContext* context, TfLiteNode* node) { |
| 32 | const TfLiteTensor* input = GetInput(context, node, kInputTensor); |
| 33 | TfLiteTensor* output = GetOutput(context, node, kOutputTensor); |
| 34 | // Tensorflow's Reshape allows one of the shape components to have the |
| 35 | // special -1 value, meaning it will be calculated automatically based on the |
| 36 | // input. Here we calculate what that dimension should be so that the number |
| 37 | // of output elements in the same as the number of input elements. |
| 38 | int num_input_elements = NumElements(input); |
| 39 | TfLiteIntArray* output_shape = output->dims; |
| 40 | |
| 41 | if (NumInputs(node) == 1 && // Legacy scalar supported with params. |
| 42 | output_shape->size == 1 && output_shape->data[0] == 0) { |
| 43 | // Legacy tflite models use a shape parameter of [0] to indicate scalars, |
| 44 | // so adjust accordingly. TODO(b/111614235): Allow zero-sized buffers during |
| 45 | // toco conversion. |
| 46 | output_shape->size = 0; |
| 47 | } |
| 48 | |
| 49 | int num_output_elements = 1; |
| 50 | int stretch_dim = -1; |
| 51 | for (int i = 0; i < output_shape->size; ++i) { |
| 52 | int value = output_shape->data[i]; |
| 53 | if (value == -1) { |
| 54 | TF_LITE_ENSURE_EQ(context, stretch_dim, -1); |
| 55 | stretch_dim = i; |
| 56 | } else { |
| 57 | num_output_elements *= value; |
| 58 | } |
| 59 | } |
| 60 | if (stretch_dim != -1) { |
| 61 | output_shape->data[stretch_dim] = num_input_elements / num_output_elements; |
| 62 | num_output_elements *= output_shape->data[stretch_dim]; |
| 63 | } |
| 64 | |
| 65 | TF_LITE_ENSURE_EQ(context, input->type, output->type); |
| 66 | TF_LITE_ENSURE_EQ(context, num_input_elements, num_output_elements); |
| 67 | return kTfLiteOk; |
| 68 | } |
| 69 | |
| 70 | TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { |
| 71 | TF_LITE_ENSURE(context, NumInputs(node) == 1 || NumInputs(node) == 2); |
no test coverage detected