| 86 | } |
| 87 | |
| 88 | TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { |
| 89 | auto* params = reinterpret_cast<TfLiteSkipGramParams*>(node->builtin_data); |
| 90 | |
| 91 | // Split sentence to words. |
| 92 | std::vector<StringRef> words; |
| 93 | tflite::StringRef strref = tflite::GetString(GetInput(context, node, 0), 0); |
| 94 | int prev_idx = 0; |
| 95 | for (int i = 1; i < strref.len; i++) { |
| 96 | if (isspace(*(strref.str + i))) { |
| 97 | if (i > prev_idx && !isspace(*(strref.str + prev_idx))) { |
| 98 | words.push_back({strref.str + prev_idx, i - prev_idx}); |
| 99 | } |
| 100 | prev_idx = i + 1; |
| 101 | } |
| 102 | } |
| 103 | if (strref.len > prev_idx) { |
| 104 | words.push_back({strref.str + prev_idx, strref.len - prev_idx}); |
| 105 | } |
| 106 | |
| 107 | // Generate n-grams recursively. |
| 108 | tflite::DynamicBuffer buf; |
| 109 | if (words.size() < params->ngram_size) { |
| 110 | buf.WriteToTensorAsVector(GetOutput(context, node, 0)); |
| 111 | return kTfLiteOk; |
| 112 | } |
| 113 | |
| 114 | // Stack stores the index of word used to generate ngram. |
| 115 | // The size of stack is the size of ngram. |
| 116 | std::vector<int> stack(params->ngram_size, 0); |
| 117 | // Stack index that indicates which depth the recursion is operating at. |
| 118 | int stack_idx = 1; |
| 119 | int num_words = words.size(); |
| 120 | |
| 121 | while (stack_idx >= 0) { |
| 122 | if (ShouldStepInRecursion(params, stack, stack_idx, num_words)) { |
| 123 | // When current depth can fill with a new word |
| 124 | // and the new word is within the max range to skip, |
| 125 | // fill this word to stack, recurse into next depth. |
| 126 | stack[stack_idx]++; |
| 127 | stack_idx++; |
| 128 | if (stack_idx < params->ngram_size) { |
| 129 | stack[stack_idx] = stack[stack_idx - 1]; |
| 130 | } |
| 131 | } else { |
| 132 | if (ShouldIncludeCurrentNgram(params, stack_idx)) { |
| 133 | // Add n-gram to tensor buffer when the stack has filled with enough |
| 134 | // words to generate the ngram. |
| 135 | std::vector<StringRef> gram(stack_idx); |
| 136 | for (int i = 0; i < stack_idx; i++) { |
| 137 | gram[i] = words[stack[i]]; |
| 138 | } |
| 139 | buf.AddJoinedString(gram, ' '); |
| 140 | } |
| 141 | // When current depth cannot fill with a valid new word, |
| 142 | // and not in last depth to generate ngram, |
| 143 | // step back to previous depth to iterate to next possible word. |
| 144 | stack_idx--; |
| 145 | } |
nothing calls this directly
no test coverage detected