#include #include #include #include namespace DB { template inline std::enable_if_t && (sizeof(T) <= sizeof(UInt32)), T> roundDownToPowerOfTwo(T x) { return x <= 0 ? 0 : (T(1) << (31 - __builtin_clz(x))); } template inline std::enable_if_t && (sizeof(T) == sizeof(UInt64)), T> roundDownToPowerOfTwo(T x) { return x <= 0 ? 0 : (T(1) << (63 - __builtin_clzll(x))); } template inline std::enable_if_t, T> roundDownToPowerOfTwo(T x) { return ext::bit_cast(ext::bit_cast(x) & ~((1ULL << 23) - 1)); } template inline std::enable_if_t, T> roundDownToPowerOfTwo(T x) { return ext::bit_cast(ext::bit_cast(x) & ~((1ULL << 52) - 1)); } /** For integer data types: * - if number is greater than zero, round it down to nearest power of two (example: roundToExp2(100) = 64, roundToExp2(64) = 64); * - otherwise, return 0. * * For floating point data types: zero out mantissa, but leave exponent. * - if number is greater than zero, round it down to nearest power of two (example: roundToExp2(3) = 2); * - negative powers are also used (example: roundToExp2(0.7) = 0.5); * - if number is zero, return zero; * - if number is less than zero, the result is symmetrical: roundToExp2(x) = -roundToExp2(-x). (example: roundToExp2(-0.3) = -0.25); */ template struct RoundToExp2Impl { using ResultType = T; static constexpr const bool allow_fixed_string = false; static inline T apply(T x) { return roundDownToPowerOfTwo(x); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = false; #endif }; struct NameRoundToExp2 { static constexpr auto name = "roundToExp2"; }; using FunctionRoundToExp2 = FunctionUnaryArithmetic; template <> struct FunctionUnaryArithmeticMonotonicity : PositiveMonotonicity {}; void registerFunctionRoundToExp2(FunctionFactory & factory) { factory.registerFunction(); } }