Resize the output and state tensors based on the sizes of the input tensors. Allocate a temporary scratch tensor. Also check that the sizes of the input tensors match each other.
| 307 | // Allocate a temporary scratch tensor. Also check that the sizes of the input |
| 308 | // tensors match each other. |
| 309 | TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { |
| 310 | OpData* op_data = reinterpret_cast<OpData*>(node->user_data); |
| 311 | const int scratch_tensor_index = op_data->scratch_tensor_index; |
| 312 | |
| 313 | // Check we have all the inputs and outputs we need. |
| 314 | bool is_layer_norm_lstm = false; |
| 315 | if (node->inputs->size == 24) { |
| 316 | const TfLiteTensor* forget_layer_norm_coefficients = GetOptionalInputTensor( |
| 317 | context, node, kForgetLayerNormCoefficientsTensor); |
| 318 | if (forget_layer_norm_coefficients == nullptr) { |
| 319 | is_layer_norm_lstm = false; |
| 320 | } else { |
| 321 | is_layer_norm_lstm = true; |
| 322 | } |
| 323 | } else if (node->inputs->size == 20) { |
| 324 | // This is deprecated and is only kept here for backward compatibility. |
| 325 | is_layer_norm_lstm = false; |
| 326 | } else { |
| 327 | context->ReportError( |
| 328 | context, "The LSTM Full kernel expects 20 or 24 inputs. Got %d inputs", |
| 329 | node->inputs->size); |
| 330 | return kTfLiteError; |
| 331 | } |
| 332 | TF_LITE_ENSURE_EQ(context, node->outputs->size, 1); |
| 333 | op_data->is_layer_norm_lstm = is_layer_norm_lstm; |
| 334 | |
| 335 | // Inferring batch size, number of outputs and sequence length and |
| 336 | // number of cells from the input tensors. |
| 337 | const TfLiteTensor* input = GetInput(context, node, kInputTensor); |
| 338 | TF_LITE_ENSURE_EQ(context, input->type, kTfLiteFloat32); |
| 339 | TF_LITE_ENSURE(context, input->dims->size > 1); |
| 340 | const auto* params = |
| 341 | reinterpret_cast<TfLiteUnidirectionalSequenceLSTMParams*>( |
| 342 | node->builtin_data); |
| 343 | const bool time_major = params->time_major; |
| 344 | const int n_batch = time_major ? input->dims->data[1] : input->dims->data[0]; |
| 345 | const int n_input = input->dims->data[2]; |
| 346 | |
| 347 | const TfLiteTensor* input_to_output_weights = |
| 348 | GetInput(context, node, kInputToOutputWeightsTensor); |
| 349 | const int n_cell = input_to_output_weights->dims->data[0]; |
| 350 | TF_LITE_ENSURE_EQ(context, input_to_output_weights->dims->size, 2); |
| 351 | TF_LITE_ENSURE_EQ(context, input_to_output_weights->dims->data[1], n_input); |
| 352 | |
| 353 | const TfLiteTensor* recurrent_to_output_weights = |
| 354 | GetInput(context, node, kRecurrentToOutputWeightsTensor); |
| 355 | TF_LITE_ENSURE_EQ(context, recurrent_to_output_weights->dims->size, 2); |
| 356 | TF_LITE_ENSURE_EQ(context, recurrent_to_output_weights->dims->data[0], |
| 357 | n_cell); |
| 358 | const int n_output = recurrent_to_output_weights->dims->data[1]; |
| 359 | |
| 360 | // Check that input tensor dimensions matches with each other. |
| 361 | TF_LITE_ENSURE_OK(context, |
| 362 | CheckInputTensorDimensions(context, node, n_input, n_output, |
| 363 | n_cell, is_layer_norm_lstm)); |
| 364 | |
| 365 | // Get the pointer to output, activation_state and cell_state buffer tensors. |
| 366 | TfLiteTensor* output = GetOutput(context, node, kOutputTensor); |
nothing calls this directly
no test coverage detected