#include #include #include #if __SSE2__ #define LIBDIVIDE_USE_SSE2 1 #endif #include namespace DB { template IColumn::Selector createBlockSelector( const IColumn & column, size_t num_shards, const std::vector & slots) { const auto total_weight = slots.size(); size_t num_rows = column.size(); IColumn::Selector selector(num_rows); /** Modulo of division of negative numbers to positive number in C++11 is negative (so called truncated division). * This is not suitable for our task. So we will process signed numbers as unsigned. * It is not near like remainder of division, but is suitable for our task. */ using UnsignedT = typename std::make_unsigned::type; /// const columns contain only one value, therefore we do not need to read it at every iteration if (column.isConst()) { const auto data = typeid_cast &>(column).getData(); const auto shard_num = slots[static_cast(data) % total_weight]; selector.assign(num_rows, shard_num); } else { /// libdivide support only UInt32 and UInt64. using TUInt32Or64 = typename std::conditional::type; libdivide::divider divider(total_weight); const auto & data = typeid_cast &>(column).getData(); for (size_t i = 0; i < num_rows; ++i) selector[i] = slots[static_cast(data[i]) - (static_cast(data[i]) / divider) * total_weight]; } return selector; } /// Explicit instantinations to avoid code bloat in headers. template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); template IColumn::Selector createBlockSelector(const IColumn & column, size_t num_shards, const std::vector & slots); }