1#include <Functions/FunctionFactory.h>
2#include <Functions/FunctionUnaryArithmetic.h>
3#include <Common/FieldVisitors.h>
4#include <Common/intExp.h>
5
6namespace DB
7{
8
9template <typename A>
10struct IntExp2Impl
11{
12 using ResultType = UInt64;
13
14 static inline ResultType apply(A a)
15 {
16 return intExp2(a);
17 }
18
19#if USE_EMBEDDED_COMPILER
20 static constexpr bool compilable = true;
21
22 static inline llvm::Value * compile(llvm::IRBuilder<> & b, llvm::Value * arg, bool)
23 {
24 if (!arg->getType()->isIntegerTy())
25 throw Exception("IntExp2Impl expected an integral type", ErrorCodes::LOGICAL_ERROR);
26 return b.CreateShl(llvm::ConstantInt::get(arg->getType(), 1), arg);
27 }
28#endif
29};
30
31/// Assumed to be injective for the purpose of query optimization, but in fact it is not injective because of possible overflow.
32struct NameIntExp2 { static constexpr auto name = "intExp2"; };
33using FunctionIntExp2 = FunctionUnaryArithmetic<IntExp2Impl, NameIntExp2, true>;
34
35template <> struct FunctionUnaryArithmeticMonotonicity<NameIntExp2>
36{
37 static bool has() { return true; }
38 static IFunction::Monotonicity get(const Field & left, const Field & right)
39 {
40 Float64 left_float = left.isNull() ? -std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), left);
41 Float64 right_float = right.isNull() ? std::numeric_limits<Float64>::infinity() : applyVisitor(FieldVisitorConvertToNumber<Float64>(), right);
42
43 if (left_float < 0 || right_float > 63)
44 return {};
45
46 return { true };
47 }
48};
49
50void registerFunctionIntExp2(FunctionFactory & factory)
51{
52 factory.registerFunction<FunctionIntExp2>();
53}
54
55}
56