#include #include #include #include namespace DB { template struct AbsImpl { using ResultType = std::conditional_t, A, typename NumberTraits::ResultOfAbs::Type>; static constexpr bool allow_string_or_fixed_string = false; static inline NO_SANITIZE_UNDEFINED ResultType apply(A a) { if constexpr (is_decimal) return a < A(0) ? A(-a) : a; else if constexpr (is_big_int_v && is_signed_v) return (a < 0) ? -a : a; else if constexpr (is_integer && is_signed_v) return a < 0 ? static_cast(~a) + 1 : static_cast(a); else if constexpr (is_integer && is_unsigned_v) return static_cast(a); else if constexpr (std::is_floating_point_v) return static_cast(std::abs(a)); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = false; /// special type handling, some other time #endif }; struct NameAbs { static constexpr auto name = "abs"; }; using FunctionAbs = FunctionUnaryArithmetic; template <> struct FunctionUnaryArithmeticMonotonicity { static bool has() { return true; } static IFunction::Monotonicity get(const Field & left, const Field & right) { Float64 left_float = left.isNull() ? -std::numeric_limits::infinity() : applyVisitor(FieldVisitorConvertToNumber(), left); Float64 right_float = right.isNull() ? std::numeric_limits::infinity() : applyVisitor(FieldVisitorConvertToNumber(), right); if ((left_float < 0 && right_float > 0) || (left_float > 0 && right_float < 0)) return {}; return { .is_monotonic = true, .is_positive = left_float > 0, .is_strict = true, }; } }; REGISTER_FUNCTION(Abs) { factory.registerFunction({}, FunctionFactory::CaseInsensitive); } }