#include #include #include #ifdef __SSE2__ #define LIBDIVIDE_USE_SSE2 1 #endif #include namespace DB { /// Optimizations for integer division by a constant. template struct DivideIntegralByConstantImpl : BinaryOperationImplBase> { using ResultType = typename DivideIntegralImpl::ResultType; static const constexpr bool allow_fixed_string = false; static void vector_constant(const PaddedPODArray & a, B b, PaddedPODArray & c) { if (unlikely(b == 0)) throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" if (unlikely(is_signed_v && b == -1)) { size_t size = a.size(); for (size_t i = 0; i < size; ++i) c[i] = -a[i]; return; } #pragma GCC diagnostic pop libdivide::divider divider(b); size_t size = a.size(); const A * a_pos = a.data(); const A * a_end = a_pos + size; ResultType * c_pos = c.data(); #ifdef __SSE2__ static constexpr size_t values_per_sse_register = 16 / sizeof(A); const A * a_end_sse = a_pos + size / values_per_sse_register * values_per_sse_register; while (a_pos < a_end_sse) { _mm_storeu_si128(reinterpret_cast<__m128i *>(c_pos), _mm_loadu_si128(reinterpret_cast(a_pos)) / divider); a_pos += values_per_sse_register; c_pos += values_per_sse_register; } #endif while (a_pos < a_end) { *c_pos = *a_pos / divider; ++a_pos; ++c_pos; } } }; /** Specializations are specified for dividing numbers of the type UInt64 and UInt32 by the numbers of the same sign. * Can be expanded to all possible combinations, but more code is needed. */ template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; template <> struct BinaryOperationImpl> : DivideIntegralByConstantImpl {}; struct NameIntDiv { static constexpr auto name = "intDiv"; }; using FunctionIntDiv = FunctionBinaryArithmetic; void registerFunctionIntDiv(FunctionFactory & factory) { factory.registerFunction(); } }