diff options
| author | vitalyisaev <[email protected]> | 2023-11-14 09:58:56 +0300 |
|---|---|---|
| committer | vitalyisaev <[email protected]> | 2023-11-14 10:20:20 +0300 |
| commit | c2b2dfd9827a400a8495e172a56343462e3ceb82 (patch) | |
| tree | cd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/Functions/bitShiftRight.cpp | |
| parent | d4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (diff) | |
YQ Connector: move tests from yql to ydb (OSS)
Перенос папки с тестами на Коннектор из папки yql в папку ydb (синхронизируется с github).
Diffstat (limited to 'contrib/clickhouse/src/Functions/bitShiftRight.cpp')
| -rw-r--r-- | contrib/clickhouse/src/Functions/bitShiftRight.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/contrib/clickhouse/src/Functions/bitShiftRight.cpp b/contrib/clickhouse/src/Functions/bitShiftRight.cpp new file mode 100644 index 00000000000..21a0f7584aa --- /dev/null +++ b/contrib/clickhouse/src/Functions/bitShiftRight.cpp @@ -0,0 +1,146 @@ +#include <Functions/FunctionFactory.h> +#include <Functions/FunctionBinaryArithmetic.h> +#include <base/hex.h> + +namespace DB +{ +namespace ErrorCodes +{ + extern const int NOT_IMPLEMENTED; + extern const int LOGICAL_ERROR; +} + +namespace +{ + +template <typename A, typename B> +struct BitShiftRightImpl +{ + using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; + static const constexpr bool allow_fixed_string = false; + static const constexpr bool allow_string_integer = true; + + template <typename Result = ResultType> + static inline NO_SANITIZE_UNDEFINED Result apply(A a [[maybe_unused]], B b [[maybe_unused]]) + { + if constexpr (is_big_int_v<B>) + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftRight is not implemented for big integers as second argument"); + else if constexpr (is_big_int_v<A>) + return static_cast<Result>(a) >> static_cast<UInt32>(b); + else + return static_cast<Result>(a) >> static_cast<Result>(b); + } + + static inline NO_SANITIZE_UNDEFINED void bitShiftRightForBytes(const UInt8 * op_pointer, const UInt8 * begin, UInt8 * out, const size_t shift_right_bits) + { + while (op_pointer > begin) + { + op_pointer--; + out--; + *out = *op_pointer >> shift_right_bits; + if (op_pointer - 1 >= begin) + { + /// The right b bit of the left byte is moved to the left b bit of this byte + *out = static_cast<UInt8>(static_cast<UInt8>(*(op_pointer - 1) << (8 - shift_right_bits)) | *out); + } + } + } + + /// For String + 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) + { + if constexpr (is_big_int_v<B>) + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftRight is not implemented for big integers as second argument"); + else + { + UInt8 word_size = 8; + /// To prevent overflow + if (static_cast<double>(b) >= (static_cast<double>(end - pos) * word_size) || b < 0) + { + /// insert default value + out_vec.push_back(0); + out_offsets.push_back(out_offsets.back() + 1); + return; + } + + size_t shift_right_bytes = b / word_size; + size_t shift_right_bits = b % word_size; + + const UInt8 * begin = pos; + const UInt8 * shift_right_end = end - shift_right_bytes; + + const size_t old_size = out_vec.size(); + size_t length = shift_right_end - begin; + const size_t new_size = old_size + length + 1; + out_vec.resize(new_size); + out_vec[old_size + length] = 0; + + /// We start from the byte on the right and shift right shift_right_bits bit by byte + UInt8 * op_pointer = const_cast<UInt8 *>(shift_right_end); + UInt8 * out = out_vec.data() + old_size + length; + bitShiftRightForBytes(op_pointer, begin, out, shift_right_bits); + out_offsets.push_back(new_size); + } + } + + /// For FixedString + 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) + { + if constexpr (is_big_int_v<B>) + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "BitShiftRight is not implemented for big integers as second argument"); + else + { + UInt8 word_size = 8; + size_t n = end - pos; + /// To prevent overflow + if (static_cast<double>(b) >= (static_cast<double>(n) * word_size) || b < 0) + { + // insert default value + out_vec.resize_fill(out_vec.size() + n); + return; + } + + size_t shift_right_bytes = b / word_size; + size_t shift_right_bits = b % word_size; + + const UInt8 * begin = pos; + const UInt8 * shift_right_end = end - shift_right_bytes; + + const size_t old_size = out_vec.size(); + const size_t new_size = old_size + n; + + /// Fill 0 to the left + out_vec.resize_fill(out_vec.size() + old_size + shift_right_bytes); + out_vec.resize(new_size); + + /// We start from the byte on the right and shift right shift_right_bits bit by byte + UInt8 * op_pointer = const_cast<UInt8 *>(shift_right_end); + UInt8 * out = out_vec.data() + new_size; + bitShiftRightForBytes(op_pointer, begin, out, shift_right_bits); + } + } + +#if USE_EMBEDDED_COMPILER + static constexpr bool compilable = true; + + static inline llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * left, llvm::Value * right, bool is_signed) + { + if (!left->getType()->isIntegerTy()) + throw Exception(ErrorCodes::LOGICAL_ERROR, "BitShiftRightImpl expected an integral type"); + return is_signed ? b.CreateAShr(left, right) : b.CreateLShr(left, right); + } +#endif +}; + + +struct NameBitShiftRight { static constexpr auto name = "bitShiftRight"; }; +using FunctionBitShiftRight = BinaryArithmeticOverloadResolver<BitShiftRightImpl, NameBitShiftRight, true, false>; + +} + +REGISTER_FUNCTION(BitShiftRight) +{ + factory.registerFunction<FunctionBitShiftRight>(); +} + +} |
