bool SortedVectorStore<V>::Inc(int32_t key, V delta, size_t *size) { if (delta == V(0)) return true; int32_t vector_idx = FindIndex(key); // Not found, insert it. if (vector_idx == -1) { if (num_entries_ == capacity_) { *size = capacity_ + kBlockSize; return false; } vector_idx = num_entries_; ++num_entries_; entries_[vector_idx].first = key; entries_[vector_idx].second = delta; // move backwards LinearSearchAndMove(vector_idx, false); return true; } // Found entries_[vector_idx].second += delta; if (entries_[vector_idx].second == V(0)) { RemoveOneEntryAndCompact(vector_idx); } return true; }
void SortedVectorMapRow<V>::ApplyDenseBatchIncUnsafe( const void* update_batch, int32_t index_st, int32_t num_updates) { const V* typed_updates = reinterpret_cast<const V*>(update_batch); // Use ApplyInc individually on each column_id. for (int i = 0; i < num_updates; ++i) { int32_t col_id = i + index_st; int32_t vector_idx = FindIndex(col_id); if (vector_idx != -1) { entries_[vector_idx].second += typed_updates[i]; // Remove vector_idx if vector_idx becomes 0. if (entries_[vector_idx].second == V(0)) { RemoveOneEntryAndCompact(vector_idx); } continue; } // Add a new entry. if (num_entries_ == capacity_) { ResetCapacity(capacity_ + K_BLOCK_SIZE_); } entries_[num_entries_].first = col_id; entries_[num_entries_].second = typed_updates[i]; ++num_entries_; } // Global sort. std::sort(entries_.get(), entries_.get() + num_entries_, [](const Entry<V>& i, const Entry<V>&j) { return i.second > j.second; }); }
void SortedVectorMapRow<V>::ApplyIncUnsafe(int32_t column_id, const void *update) { // Go through the array and find column_id int32_t vector_idx = FindIndex(column_id); V typed_update = *(reinterpret_cast<const V*>(update)); if (vector_idx != -1) { entries_[vector_idx].second += typed_update; // Remove vector_idx if vector_idx becomes 0. if (entries_[vector_idx].second == V(0)) { RemoveOneEntryAndCompact(vector_idx); return; } // Move vector_idx to maintain sorted order. bool forward = typed_update <= V(0); LinearSearchAndMove(vector_idx, forward); return; } // Add a new entry. if (num_entries_ == capacity_) { ResetCapacity(capacity_ + K_BLOCK_SIZE_); } entries_[num_entries_].first = column_id; entries_[num_entries_].second = typed_update; ++num_entries_; // Move new entry to maintain sorted order. Always move backward. LinearSearchAndMove(num_entries_ - 1, false); }
double SortedVectorMapRow<V>::ApplyBatchIncUnsafeGetImportance( const int32_t *column_ids, const void* updates, int32_t num_updates) { const V* typed_updates = reinterpret_cast<const V*>(updates); double accum_importance = 0.0; // Use ApplyInc individually on each column_id. for (int i = 0; i < num_updates; ++i) { int32_t vector_idx = FindIndex(column_ids[i]); if (vector_idx != -1) { entries_[vector_idx].second += typed_updates[i]; accum_importance += std::abs((double(entries_[vector_idx].second) == 0) ? double(typed_updates[i]) : double(typed_updates[i]) / double(entries_[vector_idx].second)); // Remove vector_idx if vector_idx becomes 0. if (entries_[vector_idx].second == V(0)) { RemoveOneEntryAndCompact(vector_idx); } continue; } // Add a new entry. if (num_entries_ == capacity_) { ResetCapacity(capacity_ + K_BLOCK_SIZE_); } entries_[num_entries_].first = column_ids[i]; entries_[num_entries_].second = typed_updates[i]; ++num_entries_; accum_importance += std::abs(typed_updates[i]); } // Global sort. std::sort(entries_.get(), entries_.get() + num_entries_, [](const Entry<V>& i, const Entry<V>&j) { return i.second > j.second; }); return std::abs(accum_importance); }