| 95 | |
| 96 | template <typename T> |
| 97 | int Eval(EvalData<T>* eval_data, int current_dim, int flat_index, |
| 98 | int output_index) { |
| 99 | if (current_dim == eval_data->num_dims) { |
| 100 | // Base case if we finished evaluating. |
| 101 | if (output_index >= eval_data->output_size) { |
| 102 | return output_index; |
| 103 | } |
| 104 | eval_data->output_data[output_index] = eval_data->input_data[flat_index]; |
| 105 | return output_index + 1; |
| 106 | } |
| 107 | // Check if the value is computed already. |
| 108 | const int cache_index = current_dim * eval_data->input_size + flat_index; |
| 109 | auto& cache_entry = eval_data->cache[cache_index]; |
| 110 | if (cache_entry.start != -1) { |
| 111 | // Cache value is (start, end) interval. We can just copy the interval |
| 112 | // directly. |
| 113 | const int count = cache_entry.end - cache_entry.start; |
| 114 | memcpy(eval_data->output_data + output_index, |
| 115 | eval_data->output_data + cache_entry.start, count * sizeof(T)); |
| 116 | return output_index + count; |
| 117 | } |
| 118 | cache_entry.start = output_index; |
| 119 | int64_t left_pad = 0, right_pad = 0; |
| 120 | const int multiplier = (*eval_data->dimension_num_elements)[current_dim]; |
| 121 | const TfLiteTensor* padding_matrix = eval_data->padding_matrix; |
| 122 | const auto offset = eval_data->offset; |
| 123 | auto* dims = eval_data->input_dims; |
| 124 | |
| 125 | GetPadding(padding_matrix, current_dim, &left_pad, &right_pad); |
| 126 | // Left padding |
| 127 | for (int i = left_pad + offset - 1; i >= offset && left_pad > 0; |
| 128 | --i, --left_pad) { |
| 129 | output_index = Eval(eval_data, current_dim + 1, flat_index + i * multiplier, |
| 130 | output_index); |
| 131 | } |
| 132 | // Original values. |
| 133 | for (int i = 0; i < dims->data[current_dim]; ++i) { |
| 134 | output_index = Eval(eval_data, current_dim + 1, flat_index + i * multiplier, |
| 135 | output_index); |
| 136 | } |
| 137 | // Right padding. |
| 138 | for (int i = dims->data[current_dim] - (1 + offset); i >= 0 && right_pad > 0; |
| 139 | --i, --right_pad) { |
| 140 | output_index = Eval(eval_data, current_dim + 1, flat_index + i * multiplier, |
| 141 | output_index); |
| 142 | } |
| 143 | cache_entry.end = output_index; |
| 144 | return output_index; |
| 145 | } |
| 146 | |
| 147 | // Returns the shape of the final output after padding. |
| 148 | std::unique_ptr<TfLiteIntArray, void (*)(TfLiteIntArray*)> GetPaddedOutputShape( |
nothing calls this directly
no test coverage detected