| 2490 | } |
| 2491 | |
| 2492 | inline void LstmCell( |
| 2493 | const LstmCellParams& params, const RuntimeShape& unextended_input_shape, |
| 2494 | const float* input_data, const RuntimeShape& unextended_prev_activ_shape, |
| 2495 | const float* prev_activ_data, const RuntimeShape& weights_shape, |
| 2496 | const float* weights_data, const RuntimeShape& unextended_bias_shape, |
| 2497 | const float* bias_data, const RuntimeShape& unextended_prev_state_shape, |
| 2498 | const float* prev_state_data, |
| 2499 | const RuntimeShape& unextended_output_state_shape, float* output_state_data, |
| 2500 | const RuntimeShape& unextended_output_activ_shape, float* output_activ_data, |
| 2501 | const RuntimeShape& unextended_concat_temp_shape, float* concat_temp_data, |
| 2502 | const RuntimeShape& unextended_activ_temp_shape, float* activ_temp_data, |
| 2503 | CpuBackendContext* cpu_backend_context) { |
| 2504 | gemmlowp::ScopedProfilingLabel label("LstmCell"); |
| 2505 | TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); |
| 2506 | TFLITE_DCHECK_LE(unextended_prev_activ_shape.DimensionsCount(), 4); |
| 2507 | TFLITE_DCHECK_LE(unextended_bias_shape.DimensionsCount(), 4); |
| 2508 | TFLITE_DCHECK_LE(unextended_prev_state_shape.DimensionsCount(), 4); |
| 2509 | TFLITE_DCHECK_LE(unextended_output_state_shape.DimensionsCount(), 4); |
| 2510 | TFLITE_DCHECK_LE(unextended_output_activ_shape.DimensionsCount(), 4); |
| 2511 | TFLITE_DCHECK_LE(unextended_concat_temp_shape.DimensionsCount(), 4); |
| 2512 | TFLITE_DCHECK_LE(unextended_activ_temp_shape.DimensionsCount(), 4); |
| 2513 | const RuntimeShape input_shape = |
| 2514 | RuntimeShape::ExtendedShape(4, unextended_input_shape); |
| 2515 | const RuntimeShape prev_activ_shape = |
| 2516 | RuntimeShape::ExtendedShape(4, unextended_prev_activ_shape); |
| 2517 | const RuntimeShape bias_shape = |
| 2518 | RuntimeShape::ExtendedShape(4, unextended_bias_shape); |
| 2519 | const RuntimeShape prev_state_shape = |
| 2520 | RuntimeShape::ExtendedShape(4, unextended_prev_state_shape); |
| 2521 | const RuntimeShape output_state_shape = |
| 2522 | RuntimeShape::ExtendedShape(4, unextended_output_state_shape); |
| 2523 | const RuntimeShape output_activ_shape = |
| 2524 | RuntimeShape::ExtendedShape(4, unextended_output_activ_shape); |
| 2525 | const RuntimeShape concat_temp_shape = |
| 2526 | RuntimeShape::ExtendedShape(4, unextended_concat_temp_shape); |
| 2527 | const RuntimeShape activ_temp_shape = |
| 2528 | RuntimeShape::ExtendedShape(4, unextended_activ_temp_shape); |
| 2529 | TFLITE_DCHECK_GE(weights_shape.DimensionsCount(), 2); |
| 2530 | |
| 2531 | const int weights_dim_count = weights_shape.DimensionsCount(); |
| 2532 | MatchingDim( // batches |
| 2533 | input_shape, 0, prev_activ_shape, 0, prev_state_shape, 0, |
| 2534 | output_state_shape, 0, output_activ_shape, 0); |
| 2535 | MatchingDim( // height |
| 2536 | input_shape, 1, prev_activ_shape, 1, prev_state_shape, 1, |
| 2537 | output_state_shape, 1, output_activ_shape, 1); |
| 2538 | MatchingDim( // width |
| 2539 | input_shape, 2, prev_activ_shape, 2, prev_state_shape, 2, |
| 2540 | output_state_shape, 2, output_activ_shape, 2); |
| 2541 | const int input_depth = input_shape.Dims(3); |
| 2542 | const int prev_activ_depth = prev_activ_shape.Dims(3); |
| 2543 | const int total_input_depth = prev_activ_depth + input_depth; |
| 2544 | TFLITE_DCHECK_EQ(weights_shape.Dims(weights_dim_count - 1), |
| 2545 | total_input_depth); |
| 2546 | TFLITE_DCHECK_EQ(FlatSizeSkipDim(bias_shape, 3), 1); |
| 2547 | const int intern_activ_depth = |
| 2548 | MatchingDim(weights_shape, weights_dim_count - 2, bias_shape, 3); |
| 2549 | TFLITE_DCHECK_EQ(weights_shape.FlatSize(), |
no test coverage detected