* @Copyright: Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
* @Description: hash util implementations
*/
#include "hash_util.h"
#include <cmath>
#include "operator/util/mm3_util.h"
namespace omniruntime {
namespace op {
uint64_t HashUtil::NextPowerOfTwo(uint64_t x)
{
if (x == 0) {
return 1;
} else {
--x;
x |= x >> ROTATE_DISTANCE_1;
x |= x >> ROTATE_DISTANCE_2;
x |= x >> ROTATE_DISTANCE_4;
x |= x >> ROTATE_DISTANCE_8;
x |= x >> ROTATE_DISTANCE_16;
return (x | (x >> ROTATE_DISTANCE_32)) + 1;
}
}
uint32_t HashUtil::HashArraySize(uint32_t expected, float f)
{
double result = static_cast<double>(expected) / static_cast<double>(f);
auto s = static_cast<uint64_t>(std::ceil(result));
s = NextPowerOfTwo(s);
if (s > MAX_ARRAY_SIZE) {
return expected;
} else {
return static_cast<uint32_t>(s);
}
}
std::unique_ptr<omniruntime::vec::Vector<int32_t>> HashUtil::ComputePartitionIds(
std::vector<omniruntime::vec::BaseVector *> &vecs, int32_t partitionNum, int32_t rowCount)
{
auto colCount = vecs.size();
std::vector<uint32_t> partitionIds(rowCount, MM3HASH_SEED);
for (auto col = 0; col < colCount; col++) {
switch (vecs[col]->GetTypeId()) {
case type::OMNI_BYTE:
case type::OMNI_SHORT:
case type::OMNI_INT:
case type::OMNI_DATE32:
Mm3Int(vecs[col], rowCount, partitionIds);
break;
case type::OMNI_LONG:
case type::OMNI_TIMESTAMP:
case type::OMNI_DECIMAL64:
case type::OMNI_DOUBLE:
Mm3Long(vecs[col], rowCount, partitionIds);
break;
case type::OMNI_CHAR:
case type::OMNI_VARCHAR:
Mm3String(vecs[col], rowCount, partitionIds);
break;
case type::OMNI_DECIMAL128:
Mm3Decimal128(vecs[col], rowCount, partitionIds);
break;
case type::OMNI_BOOLEAN:
Mm3Boolean(vecs[col], rowCount, partitionIds);
break;
default:
std::string omniExceptionInfo =
"Error in shuffle hash, not support type: " +
std::to_string(vecs[col]->GetTypeId());
throw omniruntime::exception::OmniException("UNSUPPORTED_ERROR", omniExceptionInfo);
}
}
auto ret = std::make_unique<omniruntime::vec::Vector<int>>(rowCount, type::OMNI_INT);
for (int32_t row = 0; row < rowCount; row++) {
ret->SetValue(row, Pmod(partitionIds[row], partitionNum));
}
return ret;
}
}
}