ClickHouse

Форк
0
/
bitShiftLeft.cpp 
167 строк · 5.7 Кб
1
#include <Functions/FunctionFactory.h>
2
#include <Functions/FunctionBinaryArithmetic.h>
3

4
namespace DB
5
{
6
namespace ErrorCodes
7
{
8
    extern const int NOT_IMPLEMENTED;
9
    extern const int LOGICAL_ERROR;
10
}
11

12
namespace
13
{
14

15
template <typename A, typename B>
16
struct BitShiftLeftImpl
17
{
18
    using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
19
    static const constexpr bool allow_fixed_string = false;
20
    static const constexpr bool allow_string_integer = true;
21

22
    template <typename Result = ResultType>
23
    static inline NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
24
    {
25
        if constexpr (is_big_int_v<B>)
26
            throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftLeft is not implemented for big integers as second argument");
27
        else if constexpr (is_big_int_v<A>)
28
            return static_cast<Result>(a) << static_cast<UInt32>(b);
29
        else
30
            return static_cast<Result>(a) << static_cast<Result>(b);
31
    }
32

33
    /// For String
34
    static ALWAYS_INLINE NO_SANITIZE_UNDEFINED void apply(const UInt8 * pos [[maybe_unused]], const UInt8 * end [[maybe_unused]], const B & b [[maybe_unused]], ColumnString::Chars & out_vec, ColumnString::Offsets & out_offsets)
35
    {
36
        if constexpr (is_big_int_v<B>)
37
            throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftLeft is not implemented for big integers as second argument");
38
        else
39
        {
40
            UInt8 word_size = 8;
41
            /// To prevent overflow
42
            if (static_cast<double>(b) >= (static_cast<double>(end - pos) * word_size) || b < 0)
43
            {
44
                // insert default value
45
                out_vec.push_back(0);
46
                out_offsets.push_back(out_offsets.back() + 1);
47
                return;
48
            }
49

50
            size_t shift_left_bits = b % word_size;
51
            size_t shift_left_bytes = b / word_size;
52

53
            const UInt8 * begin = pos;
54

55
            const size_t old_size = out_vec.size();
56
            size_t length;
57
            if (shift_left_bits)
58
                length = end + shift_left_bytes - begin + 1; /// Moving to the left here will make a redundant byte to store the overflowing bits in the front
59
            else
60
                length = end + shift_left_bytes - begin;
61

62
            const size_t new_size = old_size + length + 1;
63
            out_vec.resize(new_size);
64
            out_vec[old_size + length] = 0;
65

66
            UInt8 * op_pointer = const_cast<UInt8 *>(begin);
67
            UInt8 * out = out_vec.data() + old_size;
68

69
            UInt8 previous = 0;
70
            while (op_pointer < end)
71
            {
72
                if (shift_left_bits)
73
                {
74
                    /// The left b bit of the right byte is moved to the right b bit of this byte
75
                    *out = static_cast<UInt8>(static_cast<UInt8>(*(op_pointer) >> (8 - shift_left_bits)) | previous);
76
                    previous = *op_pointer << shift_left_bits;
77
                }
78
                else
79
                {
80
                    *out = *op_pointer;
81
                }
82
                op_pointer++;
83
                out++;
84
            }
85
            if (shift_left_bits)
86
            {
87
                *out = *(op_pointer - 1) << shift_left_bits;
88
                out++;
89
            }
90

91
            for (size_t i = 0; i < shift_left_bytes; ++i)
92
                *(out + i) = 0;
93

94
            out_offsets.push_back(new_size);
95
        }
96
    }
97

98
    /// For FixedString
99
    static ALWAYS_INLINE NO_SANITIZE_UNDEFINED void apply(const UInt8 * pos [[maybe_unused]], const UInt8 * end [[maybe_unused]], const B & b [[maybe_unused]], ColumnFixedString::Chars & out_vec)
100
    {
101
        if constexpr (is_big_int_v<B>)
102
            throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftLeft is not implemented for big integers as second argument");
103
        else
104
        {
105
            UInt8 word_size = 8;
106
            size_t n = end - pos;
107
            /// To prevent overflow
108
            if (static_cast<double>(b) >= (static_cast<double>(n) * word_size) || b < 0)
109
            {
110
                // insert default value
111
                out_vec.resize_fill(out_vec.size() + n);
112
                return;
113
            }
114

115
            size_t shift_left_bytes = b / word_size;
116
            size_t shift_left_bits = b % word_size;
117

118
            const UInt8 * begin = pos;
119

120
            const size_t old_size = out_vec.size();
121
            const size_t new_size = old_size + n;
122

123
            out_vec.resize(new_size);
124

125
            UInt8 * op_pointer = const_cast<UInt8 *>(begin + shift_left_bytes);
126
            UInt8 * out = out_vec.data() + old_size;
127

128
            while (op_pointer < end)
129
            {
130
                *out = *op_pointer << shift_left_bits;
131
                if (op_pointer + 1 < end)
132
                {
133
                    /// The left b bit of the right byte is moved to the right b bit of this byte
134
                    *out = static_cast<UInt8>(static_cast<UInt8>(*(op_pointer + 1) >> (8 - shift_left_bits)) | *out);
135
                }
136
                op_pointer++;
137
                out++;
138
            }
139

140
            for (size_t i = 0; i < shift_left_bytes; ++i)
141
                *(out + i) = 0;
142
        }
143
    }
144

145
#if USE_EMBEDDED_COMPILER
146
    static constexpr bool compilable = true;
147

148
    static inline llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * left, llvm::Value * right, bool)
149
    {
150
        if (!left->getType()->isIntegerTy())
151
            throw Exception(ErrorCodes::LOGICAL_ERROR, "BitShiftLeftImpl expected an integral type");
152
        return b.CreateShl(left, right);
153
    }
154
#endif
155
};
156

157
struct NameBitShiftLeft { static constexpr auto name = "bitShiftLeft"; };
158
using FunctionBitShiftLeft = BinaryArithmeticOverloadResolver<BitShiftLeftImpl, NameBitShiftLeft, true, false>;
159

160
}
161

162
REGISTER_FUNCTION(BitShiftLeft)
163
{
164
    factory.registerFunction<FunctionBitShiftLeft>();
165
}
166

167
}
168

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.