/** @file ControlGroupo * * @author Roland Conybeare, Jan 2026 **/ #pragma once #include "DArenaHashMapUtil.hpp" #include #include #include namespace xo { namespace map { namespace detail { /** @brief 16x 8-bit control bytes. * * Support optimization using SIMD operations **/ struct ControlGroup { std::array ctrl_; /** Require: lo is aligned on c_group_size (probably 16 bytes) **/ explicit ControlGroup(const uint8_t * lo) { ::memcpy(ctrl_.data(), lo, DArenaHashMapUtil::c_group_size); } /** find all exact matches in ctrl_[0..15] for @p h2. * for each match set corresponding bit in return value. * Bits {0x1, 0x2, 0x4, ...} set iff exact match on * {ctrl_[0], ctrl_[1], ctrl_2[], ...} respectively **/ uint16_t all_matches(uint8_t h2) const { uint16_t retval = 0; uint16_t bit = 1; for (auto xi : ctrl_) { if (xi == h2) retval |= bit; bit = bit << 1; } return retval; } /** find all empty sentinels in ctrl_[0..15]. * for each empty, set corresponding bit in return value. * Bits {0x1, 0x2, 0x4, ...} set iff empty spot * {ctrl_[0], ctrl_[1], ctrl_[2], ...} respectively **/ uint16_t empty_matches() const { uint16_t retval = 0; uint16_t bit = 1; for (auto xi : ctrl_) { if (xi == DArenaHashMapUtil::c_empty_slot) retval |= bit; bit = bit << 1; } return retval; } #ifdef NOT_YET __m128i ctrl; // 16 bytes loaded via SSE2 // Find all slots matching h2 uint16_t Match(uint8_t h2) const { __m128i pattern = _mm_set1_epi8(h2); __m128i result = _mm_cmpeq_epi8(ctrl, pattern); return _mm_movemask_epi8(result); // 16-bit mask } // Find all empty slots (0xFF) uint16_t MatchEmpty() const { return _mm_movemask_epi8(_mm_cmpeq_epi8(ctrl, _mm_set1_epi8(0xFF))); } #endif }; } } /*namespace map*/ } /*namespace xo*/ /* end ControlGroup.hpp */