#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 NO_INLINE void vector_constant(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size) { 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)) { for (size_t i = 0; i < size; ++i) c_pos[i] = -a_pos[i]; return; } #pragma GCC diagnostic pop libdivide::divider divider(b); const A * a_end = a_pos + size; #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(); } }