TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  auto* params = reinterpret_cast<TfLiteRNNParams*>(node->builtin_data);
  auto* op_data = reinterpret_cast<OpData*>(node->user_data);
  const TfLiteTensor* input;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, kInputTensor, &input));
  const TfLiteTensor* input_weights;
  TF_LITE_ENSURE_OK(
      context, GetInputSafe(context, node, kWeightsTensor, &input_weights));
  const TfLiteTensor* recurrent_weights;
  TF_LITE_ENSURE_OK(
      context,
      GetInputSafe(context, node, kRecurrentWeightsTensor, &recurrent_weights));
  const TfLiteTensor* bias;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, kBiasTensor, &bias));
  TfLiteTensor* hidden_state =
      GetVariableInput(context, node, kHiddenStateTensor);
  TF_LITE_ENSURE(context, hidden_state != nullptr);
  TfLiteTensor* output;
  TF_LITE_ENSURE_OK(context,
                    GetOutputSafe(context, node, kOutputTensor, &output));

  // We already checked that weight types are consistent, so branch on one.
  switch (input_weights->type) {
    case kTfLiteFloat32:
      return EvalFloat(input, input_weights, recurrent_weights, bias, params,
                       hidden_state, output);
    case kTfLiteUInt8:
    case kTfLiteInt8: {
      // TODO(mirkov): implement eval with quantized inputs as well.
      TfLiteTensor* input_quantized;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 0, &input_quantized));
      TfLiteTensor* hidden_state_quantized;
      TF_LITE_ENSURE_OK(
          context, GetTemporarySafe(context, node, 1, &hidden_state_quantized));
      TfLiteTensor* scaling_factors;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 2, &scaling_factors));
      TfLiteTensor* accum_scratch;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 3, &accum_scratch));
      TfLiteTensor* zero_points;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 4, &zero_points));
      TfLiteTensor* row_sums;
      TF_LITE_ENSURE_OK(context, GetTemporarySafe(context, node, 5, &row_sums));
      return EvalHybrid(input, input_weights, recurrent_weights, bias, params,
                        input_quantized, hidden_state_quantized,
                        scaling_factors, hidden_state, output, zero_points,
                        accum_scratch, row_sums, &op_data->compute_row_sums);
    }
    default:
      TF_LITE_KERNEL_LOG(context, "Type %s not currently supported.",
                         TfLiteTypeGetName(input_weights->type));
      return kTfLiteError;
  }
  return kTfLiteOk;
}
TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  auto* params = reinterpret_cast<TfLiteRNNParams*>(node->builtin_data);
  auto* op_data = reinterpret_cast<OpData*>(node->user_data);
  const TfLiteTensor* input;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, kInputTensor, &input));
  const TfLiteTensor* input_weights;
  TF_LITE_ENSURE_OK(
      context, GetInputSafe(context, node, kWeightsTensor, &input_weights));
  const TfLiteTensor* recurrent_weights;
  TF_LITE_ENSURE_OK(
      context,
      GetInputSafe(context, node, kRecurrentWeightsTensor, &recurrent_weights));
  const TfLiteTensor* bias;
  TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, kBiasTensor, &bias));
  TfLiteTensor* hidden_state =
      GetVariableInput(context, node, kHiddenStateTensor);
  TF_LITE_ENSURE(context, hidden_state != nullptr);
  TfLiteTensor* output;
  TF_LITE_ENSURE_OK(context,
                    GetOutputSafe(context, node, kOutputTensor, &output));

   
  switch (input_weights->type) {
    case kTfLiteFloat32:
      return EvalFloat(input, input_weights, recurrent_weights, bias, params,
                       hidden_state, output);
    case kTfLiteUInt8:
    case kTfLiteInt8: {
       
      TfLiteTensor* input_quantized;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 0, &input_quantized));
      TfLiteTensor* hidden_state_quantized;
      TF_LITE_ENSURE_OK(
          context, GetTemporarySafe(context, node, 1, &hidden_state_quantized));
      TfLiteTensor* scaling_factors;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 2, &scaling_factors));
      TfLiteTensor* accum_scratch;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 3, &accum_scratch));
      TfLiteTensor* zero_points;
      TF_LITE_ENSURE_OK(context,
                        GetTemporarySafe(context, node, 4, &zero_points));
      TfLiteTensor* row_sums;
      TF_LITE_ENSURE_OK(context, GetTemporarySafe(context, node, 5, &row_sums));
      return EvalHybrid(input, input_weights, recurrent_weights, bias, params,
                        input_quantized, hidden_state_quantized,
                        scaling_factors, hidden_state, output, zero_points,
                        accum_scratch, row_sums, &op_data->compute_row_sums);
    }
    default:
      TF_LITE_KERNEL_LOG(context, "Type %s not currently supported.",
                         TfLiteTypeGetName(input_weights->type));
      return kTfLiteError;
  }
  return kTfLiteOk;
}