| 235 | } |
| 236 | |
| 237 | TfLiteStatus EvalPie(TfLiteContext* context, TfLiteNode* node, |
| 238 | TfLiteFullyConnectedParams* params, OpData* data, |
| 239 | const TfLiteTensor* input, const TfLiteTensor* filter, |
| 240 | const TfLiteTensor* bias, TfLiteTensor* output) { |
| 241 | int total_input_size = 1; |
| 242 | for (int i = 0; i < input->dims->size; i++) { |
| 243 | total_input_size *= input->dims->data[i]; |
| 244 | } |
| 245 | |
| 246 | int input_size = filter->dims->data[1]; |
| 247 | const int batch_size = total_input_size / filter->dims->data[1]; |
| 248 | const int num_units = filter->dims->data[0]; |
| 249 | |
| 250 | // Output = bias if bias tensor exists. |
| 251 | if (bias) { |
| 252 | tensor_utils::VectorBatchVectorAssign(bias->data.f, num_units, batch_size, |
| 253 | output->data.f); |
| 254 | } else { |
| 255 | std::fill_n(output->data.f, batch_size * num_units, 0.0f); |
| 256 | } |
| 257 | |
| 258 | // Compute output += weight * input |
| 259 | tensor_utils::MatrixBatchVectorMultiplyAccumulate( |
| 260 | filter->data.f, num_units, input_size, input->data.f, batch_size, |
| 261 | output->data.f, /*result_stride=*/1); |
| 262 | |
| 263 | // Apply activation function |
| 264 | tensor_utils::ApplyActivationToVector(output->data.f, batch_size * num_units, |
| 265 | params->activation, output->data.f); |
| 266 | |
| 267 | return kTfLiteOk; |
| 268 | } |
| 269 | |
| 270 | TfLiteStatus EvalHybrid(TfLiteContext* context, TfLiteNode* node, |
| 271 | TfLiteFullyConnectedParams* params, OpData* data, |
no test coverage detected