| 240 | |
| 241 | template<typename T, typename TIndex, class HashMap> |
| 242 | void ParallelComputeV1(OpKernelContext* context, const Tensor& input, |
| 243 | Tensor* idx, int64 axis, int64* uniq_size, int num_sparse, |
| 244 | google::dense_hash_map<int, TIndex>* counter_map, Tensor* output) { |
| 245 | // Struct INode was used to store an inverse mapping for each node in the |
| 246 | // hash map container. |
| 247 | struct INode { |
| 248 | explicit INode(const TIndex index, const T& key) |
| 249 | : owner_ptr_(nullptr), index_(index), key_(key) {} |
| 250 | |
| 251 | const INode* owner_ptr_; |
| 252 | TIndex index_; |
| 253 | const T key_; |
| 254 | }; |
| 255 | |
| 256 | // Struct UniqueSubMap is used to build and operate local hash map and keep |
| 257 | // index mapping information. |
| 258 | struct UniqueSubMap { |
| 259 | public: |
| 260 | inline void Init(int64 size) { |
| 261 | next_index_ = 0; |
| 262 | HashMapInitializer<HashMap>::InitSize(&uniq_, size); |
| 263 | inodes_.reserve(size); |
| 264 | } |
| 265 | |
| 266 | inline void UniqueInsert(const T& key) { |
| 267 | auto it = uniq_.emplace(key, next_index_); |
| 268 | if (it.second) { |
| 269 | inodes_.emplace_back(INode(next_index_, key)); |
| 270 | ++next_index_; |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | inline const INode* GetINodeByPos(const TIndex pos) const { |
| 275 | const INode* inode = &inodes_[pos]; |
| 276 | return (inode->owner_ptr_ == nullptr) ? inode : inode->owner_ptr_; |
| 277 | } |
| 278 | |
| 279 | inline const INode* GetINodeByKey(const T& key) const { |
| 280 | auto item = uniq_.find(key); |
| 281 | if (item != uniq_.end()) { return GetINodeByPos(item->second); } |
| 282 | return nullptr; |
| 283 | } |
| 284 | |
| 285 | bool DeDup(const TIndex pos, const UniqueSubMap& prior_map) { |
| 286 | INode* my_inode = &inodes_[pos]; |
| 287 | if (my_inode->owner_ptr_ != nullptr) { return false; } |
| 288 | const INode* prior_inode = prior_map.GetINodeByKey(my_inode->key_); |
| 289 | if (prior_inode == nullptr) { return false; } |
| 290 | my_inode->owner_ptr_ = prior_inode; |
| 291 | return true; |
| 292 | } |
| 293 | |
| 294 | bool TryIndexAndGetKey(const TIndex pos, const TIndex new_id, T* out) { |
| 295 | INode* inode = &inodes_[pos]; |
| 296 | if (inode->owner_ptr_ != nullptr) { return false; } |
| 297 | inode->index_ = new_id; |
| 298 | *out = inode->key_; |
| 299 | return true; |
nothing calls this directly
no test coverage detected