ClickHouse
63 строки · 1.9 Кб
1#include <base/bit_cast.h>
2#include <Functions/FunctionFactory.h>
3#include <Functions/FunctionUnaryArithmetic.h>
4#include <bit>
5
6
7namespace DB
8{
9
10template <typename A>
11struct BitCountImpl
12{
13using ResultType = std::conditional_t<(sizeof(A) * 8 >= 256), UInt16, UInt8>;
14static constexpr bool allow_string_or_fixed_string = true;
15
16static inline ResultType apply(A a)
17{
18/// We count bits in the value representation in memory. For example, we support floats.
19/// We need to avoid sign-extension when converting signed numbers to larger type. So, uint8_t(-1) has 8 bits.
20
21if constexpr (is_big_int_v<A>)
22{
23ResultType res = 0;
24for (auto item : a.items)
25res += std::popcount(item);
26return res;
27}
28if constexpr (std::is_same_v<A, UInt64> || std::is_same_v<A, Int64>)
29return std::popcount(static_cast<UInt64>(a));
30if constexpr (std::is_same_v<A, UInt32> || std::is_same_v<A, Int32> || std::is_unsigned_v<A>)
31return std::popcount(static_cast<UInt32>(a));
32if constexpr (std::is_same_v<A, Int16>)
33return std::popcount(static_cast<UInt16>(a));
34if constexpr (std::is_same_v<A, Int8>)
35return std::popcount(static_cast<uint8_t>(a));
36else
37return std::popcount(bit_cast<uint64_t>(a));
38}
39
40#if USE_EMBEDDED_COMPILER
41static constexpr bool compilable = false;
42#endif
43};
44
45struct NameBitCount { static constexpr auto name = "bitCount"; };
46using FunctionBitCount = FunctionUnaryArithmetic<BitCountImpl, NameBitCount, false /* is injective */>;
47
48/// The function has no ranges of monotonicity.
49template <> struct FunctionUnaryArithmeticMonotonicity<NameBitCount>
50{
51static bool has() { return false; }
52static IFunction::Monotonicity get(const Field &, const Field &)
53{
54return {};
55}
56};
57
58REGISTER_FUNCTION(BitCount)
59{
60factory.registerFunction<FunctionBitCount>();
61}
62
63}
64