void Hll8Array::mergeHll()

in hll/include/Hll8Array-internal.hpp [115:192]


void Hll8Array<A>::mergeHll(const HllArray<A>& src) {
  // at this point src_k >= dst_k
  // we can optimize further when the k values are equal
  if (this->getLgConfigK() == src.getLgConfigK()) {
    if (src.getTgtHllType() == target_hll_type::HLL_8) {
      uint32_t i = 0;
      for (const auto value: src.getHllArray()) {
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
        ++i;
      }
    } else if (src.getTgtHllType() == target_hll_type::HLL_6) {
      const uint32_t src_k = 1 << src.getLgConfigK();
      uint32_t i = 0;
      const uint8_t* ptr = src.getHllArray().data();
      while (i < src_k) {
        uint8_t value = *ptr & 0x3f;
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
        ++i;
        value = *ptr++ >> 6;
        value |= (*ptr & 0x0f) << 2;
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
        ++i;
        value = *ptr++ >> 4;
        value |= (*ptr & 3) << 4;
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
        ++i;
        value = *ptr++ >> 2;
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
        ++i;
      }
    } else { // HLL_4
      const auto& src4 = static_cast<const Hll4Array<A>&>(src);
      uint32_t i = 0;
      for (const auto byte: src.getHllArray()) {
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], src4.adjustRawValue(i, byte & hll_constants::loNibbleMask));
        ++i;
        this->hllByteArr_[i] = std::max(this->hllByteArr_[i], src4.adjustRawValue(i, byte >> 4));
        ++i;
      }
    }
  } else {
    // src_k > dst_k
    const uint32_t dst_mask = (1 << this->getLgConfigK()) - 1;
    // special treatment below to optimize performance
    if (src.getTgtHllType() == target_hll_type::HLL_8) {
      uint32_t i = 0;
      for (const auto value: src.getHllArray()) {
        processValue(i++, dst_mask, value);
      }
    } else if (src.getTgtHllType() == target_hll_type::HLL_6) {
      const uint32_t src_k = 1 << src.getLgConfigK();
      uint32_t i = 0;
      const uint8_t* ptr = src.getHllArray().data();
      while (i < src_k) {
        uint8_t value = *ptr & 0x3f;
        processValue(i++, dst_mask, value);
        value = *ptr++ >> 6;
        value |= (*ptr & 0x0f) << 2;
        processValue(i++, dst_mask, value);
        value = *ptr++ >> 4;
        value |= (*ptr & 3) << 4;
        processValue(i++, dst_mask, value);
        value = *ptr++ >> 2;
        processValue(i++, dst_mask, value);
      }
    } else { // HLL_4
      const auto& src4 = static_cast<const Hll4Array<A>&>(src);
      uint32_t i = 0;
      for (const auto byte: src.getHllArray()) {
        processValue(i, dst_mask, src4.adjustRawValue(i, byte & hll_constants::loNibbleMask));
        ++i;
        processValue(i, dst_mask, src4.adjustRawValue(i, byte >> 4));
        ++i;
      }
    }
  }
  this->setRebuildKxqCurminFlag(true);
}