TfLiteStatus EvalInt8(TfLiteContext* context, const OpData* data,
                      const RuntimeShape& lhs_shape, const TfLiteTensor* lhs,
                      const RuntimeShape& rhs_shape, const TfLiteTensor* rhs,
                      const RuntimeShape& output_shape, TfLiteTensor* output) {
  // Reuse params struct from FullyConnected Op.
  FullyConnectedParams op_params;
  int32_t input_offset = -lhs->params.zero_point;
  int32_t filter_offset = -rhs->params.zero_point;
  int32_t output_offset = output->params.zero_point;
  op_params.input_offset = input_offset;
  op_params.weights_offset = filter_offset;
  op_params.output_offset = output_offset;
  op_params.output_multiplier = data->output_multiplier;
  op_params.output_shift = data->output_shift;
  op_params.quantized_activation_min = data->output_activation_min;
  op_params.quantized_activation_max = data->output_activation_max;
  op_params.lhs_cacheable = IsConstantTensor(lhs);
  op_params.rhs_cacheable = IsConstantTensor(rhs);

  if (kernel_type == kReference) {
    reference_ops::BatchMatMul(op_params, rhs_shape, GetTensorData<int8_t>(rhs),
                               lhs_shape, GetTensorData<int8_t>(lhs),
                               GetTensorShape(output),
                               GetTensorData<int8_t>(output));
  } else {
    optimized_ops::BatchMatMul(op_params, rhs_shape, GetTensorData<int8_t>(rhs),
                               lhs_shape, GetTensorData<int8_t>(lhs),
                               GetTensorShape(output),
                               GetTensorData<int8_t>(output),
                               CpuBackendContext::GetFromContext(context));
  }
  return kTfLiteOk;
}
TfLiteStatus EvalInt8(TfLiteContext* context, const OpData* data,
                      const RuntimeShape& lhs_shape, const TfLiteTensor* lhs,
                      const RuntimeShape& rhs_shape, const TfLiteTensor* rhs,
                      const RuntimeShape& output_shape, TfLiteTensor* output) {
   
  FullyConnectedParams op_params;
  int32_t input_offset = -lhs->params.zero_point;
  int32_t filter_offset = -rhs->params.zero_point;
  int32_t output_offset = output->params.zero_point;
  op_params.input_offset = input_offset;
  op_params.weights_offset = filter_offset;
  op_params.output_offset = output_offset;
  op_params.output_multiplier = data->output_multiplier;
  op_params.output_shift = data->output_shift;
  op_params.quantized_activation_min = data->output_activation_min;
  op_params.quantized_activation_max = data->output_activation_max;
  op_params.lhs_cacheable = IsConstantTensor(lhs);
  op_params.rhs_cacheable = IsConstantTensor(rhs);

  if (kernel_type == kReference) {
    reference_ops::BatchMatMul(op_params, rhs_shape, GetTensorData<int8_t>(rhs),
                               lhs_shape, GetTensorData<int8_t>(lhs),
                               GetTensorShape(output),
                               GetTensorData<int8_t>(output));
  } else {
    optimized_ops::BatchMatMul(op_params, rhs_shape, GetTensorData<int8_t>(rhs),
                               lhs_shape, GetTensorData<int8_t>(lhs),
                               GetTensorShape(output),
                               GetTensorData<int8_t>(output),
                               CpuBackendContext::GetFromContext(context));
  }
  return kTfLiteOk;
}