#include "mkql_builtins_decimal.h" // Y_IGNORE #include namespace NKikimr { namespace NMiniKQL { namespace { template ::value>* = nullptr> inline T Abs(T v) { return v; } template ::value>* = nullptr> inline T Abs(T v) { return std::fabs(v); } template ::value && std::is_integral::value>* = nullptr> inline T Abs(T v) { return std::abs(v); } template struct TAbs : public TSimpleArithmeticUnary> { static constexpr auto NullMode = TKernel::ENullMode::Default; static TOutput Do(TInput val) { return Abs(val); } #ifndef MKQL_DISABLE_CODEGEN static Value* Gen(Value* arg, const TCodegenContext& ctx, BasicBlock*& block) { if (std::is_unsigned()) return arg; if (std::is_floating_point()) { auto& module = ctx.Codegen.GetModule(); const auto fnType = FunctionType::get(arg->getType(), {arg->getType()}, false); const auto& name = GetFuncNameForType("llvm.fabs"); const auto func = module.getOrInsertFunction(name, fnType).getCallee(); const auto res = CallInst::Create(fnType, func, {arg}, "fabs", block); return res; } else { const auto zero = ConstantInt::get(arg->getType(), 0); const auto check = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLT, arg, zero, "check", block); const auto neg = BinaryOperator::CreateNeg(arg, "neg", block); const auto res = SelectInst::Create(check, neg, arg, "result", block); return res; } } #endif }; struct TDecimalAbs : public TDecimalUnary { static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& arg) { const auto a = arg.GetInt128(); return a < 0 ? NUdf::TUnboxedValuePod(-a) : arg; } #ifndef MKQL_DISABLE_CODEGEN static Value* Generate(Value* arg, const TCodegenContext&, BasicBlock*& block) { const auto val = GetterForInt128(arg, block); const auto zero = ConstantInt::get(val->getType(), 0); const auto check = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLT, val, zero, "check", block); const auto neg = BinaryOperator::CreateNeg(val, "neg", block); const auto res = SelectInst::Create(check, SetterForInt128(neg, block), arg, "result", block); return res; } #endif }; } void RegisterAbs(IBuiltinFunctionRegistry& registry) { RegisterUnaryNumericFunctionOpt(registry, "Abs"); RegisterFunctionUnOpt, NUdf::TDataType, TAbs, TUnaryArgsOpt>(registry, "Abs"); RegisterFunctionUnOpt, NUdf::TDataType, TAbs, TUnaryArgsOpt>(registry, "Abs"); NDecimal::RegisterUnaryFunction(registry, "Abs"); } void RegisterAbs(TKernelFamilyMap& kernelFamilyMap) { auto family = std::make_unique>(); AddUnaryDecimalKernels(*family); kernelFamilyMap["Abs"] = std::move(family); } } // namespace NMiniKQL } // namespace NKikimr