@@ -422,6 +422,20 @@ class OpenAddressHashAgg {
422422 return hash;
423423 }
424424
425+ // Fast path for int64 keys: hash of [0x02][8-byte-int64] without buffer construction
426+ static uint64_t hash_int64 (int64_t key) {
427+ uint64_t h = 14695981039346656037ull ;
428+ h ^= 0x02 ; // type tag for INT64
429+ h *= 1099511628211ull ;
430+ // XOR each byte of key in big-endian order
431+ uint64_t v = static_cast <uint64_t >(key);
432+ for (int i = 7 ; i >= 0 ; --i) {
433+ h ^= (v >> (i * 8 )) & 0xFF ;
434+ h *= 1099511628211ull ;
435+ }
436+ return h;
437+ }
438+
425439 void init (size_t capacity_hint, size_t max_aggregates) {
426440 max_aggregates_ = max_aggregates;
427441 num_occupied_ = 0 ;
@@ -487,7 +501,7 @@ class OpenAddressHashAgg {
487501 valid_indices_.push_back (idx);
488502 return bucket;
489503 }
490- if (bucket.key_type == 0x02 && bucket.key_int64 == key) {
504+ if (bucket.key_hash == hash && bucket. key_type == 0x02 && bucket.key_int64 == key) {
491505 bucket.is_new = false ;
492506 return bucket;
493507 }
@@ -520,6 +534,44 @@ class OpenAddressHashAgg {
520534 const std::vector<size_t >& valid_slots () const { return valid_indices_; }
521535 HashBucket& slot (size_t idx) { return buckets_[idx]; }
522536 const HashBucket& slot (size_t idx) const { return buckets_[idx]; }
537+
538+ /* *
539+ * @brief Insert a batch of int64 keys with precomputed hashes.
540+ * @param keys Array of int64 keys (n keys)
541+ * @param hashes Array of precomputed FNV-1a hashes (must be precomputed!)
542+ * @param n Number of keys
543+ * @return Number of new groups inserted (keys not found before)
544+ */
545+ size_t insert_batch_int64 (const int64_t * keys, const uint64_t * hashes, size_t n) {
546+ size_t new_groups = 0 ;
547+ for (size_t i = 0 ; i < n; ++i) {
548+ auto & bucket = find_or_insert_int64 (keys[i], hashes[i]);
549+ if (bucket.is_new ) {
550+ new_groups++;
551+ }
552+ }
553+ return new_groups;
554+ }
555+
556+ /* *
557+ * @brief Insert a batch of string keys with precomputed hashes.
558+ * @param keys Array of key byte arrays
559+ * @param key_lens Array of key lengths
560+ * @param hashes Array of precomputed hashes
561+ * @param n Number of keys
562+ * @return Number of new groups inserted
563+ */
564+ size_t insert_batch_bytes (const uint8_t ** keys, const size_t * key_lens,
565+ const uint64_t * hashes, size_t n) {
566+ size_t new_groups = 0 ;
567+ for (size_t i = 0 ; i < n; ++i) {
568+ auto & bucket = find_or_insert (keys[i], key_lens[i], hashes[i]);
569+ if (bucket.is_new ) {
570+ new_groups++;
571+ }
572+ }
573+ return new_groups;
574+ }
523575};
524576
525577/* *
0 commit comments