| 99 | } |
| 100 | |
| 101 | TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { |
| 102 | TfLiteTensor* output = GetOutput(context, node, 0); |
| 103 | TfLiteTensor* hits = GetOutput(context, node, 1); |
| 104 | const TfLiteTensor* lookup = GetInput(context, node, 0); |
| 105 | const TfLiteTensor* key = GetInput(context, node, 1); |
| 106 | const TfLiteTensor* value = GetInput(context, node, 2); |
| 107 | |
| 108 | const int num_rows = SizeOfDimension(value, 0); |
| 109 | const int row_bytes = value->bytes / num_rows; |
| 110 | void* pointer = nullptr; |
| 111 | DynamicBuffer buf; |
| 112 | |
| 113 | for (int i = 0; i < SizeOfDimension(lookup, 0); i++) { |
| 114 | int idx = -1; |
| 115 | pointer = bsearch(&(lookup->data.i32[i]), key->data.i32, num_rows, |
| 116 | sizeof(int32_t), greater); |
| 117 | if (pointer != nullptr) { |
| 118 | idx = (reinterpret_cast<char*>(pointer) - (key->data.raw)) / |
| 119 | sizeof(int32_t); |
| 120 | } |
| 121 | |
| 122 | if (idx >= num_rows || idx < 0) { |
| 123 | if (output->type == kTfLiteString) { |
| 124 | buf.AddString(nullptr, 0); |
| 125 | } else { |
| 126 | memset(output->data.raw + i * row_bytes, 0, row_bytes); |
| 127 | } |
| 128 | hits->data.uint8[i] = 0; |
| 129 | } else { |
| 130 | if (output->type == kTfLiteString) { |
| 131 | buf.AddString(GetString(value, idx)); |
| 132 | } else { |
| 133 | memcpy(output->data.raw + i * row_bytes, |
| 134 | value->data.raw + idx * row_bytes, row_bytes); |
| 135 | } |
| 136 | hits->data.uint8[i] = 1; |
| 137 | } |
| 138 | } |
| 139 | if (output->type == kTfLiteString) { |
| 140 | buf.WriteToTensorAsVector(output); |
| 141 | } |
| 142 | |
| 143 | return kTfLiteOk; |
| 144 | } |
| 145 | } // namespace |
| 146 | |
| 147 | TfLiteRegistration* Register_HASHTABLE_LOOKUP() { |
nothing calls this directly
no test coverage detected