aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Functions/divide/divideImpl.cpp
blob: 966d5777c1dfa3c28083a80c979a97d9622c2ac7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/// This translation unit should be compiled multiple times
/// with different values of NAMESPACE and machine flags (sse2, avx2).

/// See also <libdivide-config.h>
#if defined(__AVX2__)
    #define REG_SIZE 32
    #define LIBDIVIDE_AVX2
#elif defined(__SSE2__)
    #define REG_SIZE 16
    #define LIBDIVIDE_SSE2
#endif

#include <libdivide.h>


namespace NAMESPACE
{

template <typename A, typename B, typename ResultType>
void divideImpl(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size)
{
    libdivide::divider<A> divider(static_cast<A>(b));
    const A * a_end = a_pos + size;

#if defined(__SSE2__)
    static constexpr size_t values_per_simd_register = REG_SIZE / sizeof(A);
    const A * a_end_simd = a_pos + size / values_per_simd_register * values_per_simd_register;

    while (a_pos < a_end_simd)
    {
#if defined(__AVX2__)
        _mm256_storeu_si256(reinterpret_cast<__m256i *>(c_pos),
            _mm256_loadu_si256(reinterpret_cast<const __m256i *>(a_pos)) / divider);
#else
        _mm_storeu_si128(reinterpret_cast<__m128i *>(c_pos),
            _mm_loadu_si128(reinterpret_cast<const __m128i *>(a_pos)) / divider);
#endif

        a_pos += values_per_simd_register;
        c_pos += values_per_simd_register;
    }
#endif

    while (a_pos < a_end)
    {
        *c_pos = *a_pos / divider;
        ++a_pos;
        ++c_pos;
    }
}

template void divideImpl<uint64_t, uint64_t, uint64_t>(const uint64_t * __restrict, uint64_t, uint64_t * __restrict, size_t);
template void divideImpl<uint64_t, uint32_t, uint64_t>(const uint64_t * __restrict, uint32_t, uint64_t * __restrict, size_t);
template void divideImpl<uint64_t, uint16_t, uint64_t>(const uint64_t * __restrict, uint16_t, uint64_t * __restrict, size_t);
template void divideImpl<uint64_t, char8_t, uint64_t>(const uint64_t * __restrict, char8_t, uint64_t * __restrict, size_t);

template void divideImpl<uint32_t, uint64_t, uint32_t>(const uint32_t * __restrict, uint64_t, uint32_t * __restrict, size_t);
template void divideImpl<uint32_t, uint32_t, uint32_t>(const uint32_t * __restrict, uint32_t, uint32_t * __restrict, size_t);
template void divideImpl<uint32_t, uint16_t, uint32_t>(const uint32_t * __restrict, uint16_t, uint32_t * __restrict, size_t);
template void divideImpl<uint32_t, char8_t, uint32_t>(const uint32_t * __restrict, char8_t, uint32_t * __restrict, size_t);

template void divideImpl<int64_t, int64_t, int64_t>(const int64_t * __restrict, int64_t, int64_t * __restrict, size_t);
template void divideImpl<int64_t, int32_t, int64_t>(const int64_t * __restrict, int32_t, int64_t * __restrict, size_t);
template void divideImpl<int64_t, int16_t, int64_t>(const int64_t * __restrict, int16_t, int64_t * __restrict, size_t);
template void divideImpl<int64_t, int8_t, int64_t>(const int64_t * __restrict, int8_t, int64_t * __restrict, size_t);

template void divideImpl<int32_t, int64_t, int32_t>(const int32_t * __restrict, int64_t, int32_t * __restrict, size_t);
template void divideImpl<int32_t, int32_t, int32_t>(const int32_t * __restrict, int32_t, int32_t * __restrict, size_t);
template void divideImpl<int32_t, int16_t, int32_t>(const int32_t * __restrict, int16_t, int32_t * __restrict, size_t);
template void divideImpl<int32_t, int8_t, int32_t>(const int32_t * __restrict, int8_t, int32_t * __restrict, size_t);

}