| 203 | } |
| 204 | |
| 205 | TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { |
| 206 | auto* params = reinterpret_cast<TfLiteRNNParams*>(node->builtin_data); |
| 207 | |
| 208 | const TfLiteTensor* input = GetInput(context, node, kInputTensor); |
| 209 | const TfLiteTensor* input_weights = GetInput(context, node, kWeightsTensor); |
| 210 | const TfLiteTensor* recurrent_weights = |
| 211 | GetInput(context, node, kRecurrentWeightsTensor); |
| 212 | const TfLiteTensor* bias = GetInput(context, node, kBiasTensor); |
| 213 | TfLiteTensor* hidden_state = |
| 214 | &context->tensors[node->inputs->data[kHiddenStateTensor]]; |
| 215 | TfLiteTensor* output = GetOutput(context, node, kOutputTensor); |
| 216 | |
| 217 | // We already checked that weight types are consistent, so branch on one. |
| 218 | switch (input_weights->type) { |
| 219 | case kTfLiteFloat32: |
| 220 | return EvalFloat(input, input_weights, recurrent_weights, bias, params, |
| 221 | hidden_state, output); |
| 222 | case kTfLiteUInt8: |
| 223 | case kTfLiteInt8: { |
| 224 | // TODO(mirkov): implement eval with quantized inputs as well. |
| 225 | TfLiteTensor* input_quantized = GetTemporary(context, node, 0); |
| 226 | TfLiteTensor* hidden_state_quantized = GetTemporary(context, node, 1); |
| 227 | TfLiteTensor* scaling_factors = GetTemporary(context, node, 2); |
| 228 | return EvalHybrid(input, input_weights, recurrent_weights, bias, params, |
| 229 | input_quantized, hidden_state_quantized, |
| 230 | scaling_factors, hidden_state, output); |
| 231 | } |
| 232 | default: |
| 233 | context->ReportError(context, "Type %d not currently supported.", |
| 234 | input_weights->type); |
| 235 | return kTfLiteError; |
| 236 | } |
| 237 | return kTfLiteOk; |
| 238 | } |
| 239 | |
| 240 | } // namespace rnn |
| 241 |
nothing calls this directly
no test coverage detected