#include #include #include #include namespace DB { template struct GreatestBaseImpl { using ResultType = NumberTraits::ResultOfGreatest; static const constexpr bool allow_fixed_string = false; static const constexpr bool allow_string_integer = false; template static inline Result apply(A a, B b) { return static_cast(a) > static_cast(b) ? static_cast(a) : static_cast(b); } #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()) { /// Follows the IEEE-754 semantics for maxNum except for the handling of signaling NaNs. This matches the behavior of libc fmax. return b.CreateMaxNum(left, right); } auto * compare_value = is_signed ? b.CreateICmpSGT(left, right) : b.CreateICmpUGT(left, right); return b.CreateSelect(compare_value, left, right); } #endif }; template struct GreatestSpecialImpl { using ResultType = make_unsigned_t; static const constexpr bool allow_fixed_string = false; static const constexpr bool allow_string_integer = false; template static inline Result apply(A a, B b) { static_assert(std::is_same_v, "ResultType != Result"); return accurate::greaterOp(a, b) ? static_cast(a) : static_cast(b); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = false; /// ??? #endif }; template using GreatestImpl = std::conditional_t, GreatestBaseImpl, GreatestSpecialImpl>; struct NameGreatest { static constexpr auto name = "greatest"; }; using FunctionGreatest = FunctionBinaryArithmetic; REGISTER_FUNCTION(Greatest) { factory.registerFunction>({}, FunctionFactory::CaseInsensitive); } }